diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 000000000..4e0fb5920 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,8 @@ +exclude_patterns: +- "coverage/" +- "node_modules/" +- "test/" +- "tutorials/" +- "docs/" +- "dist/" +- "example/" diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..5d7399c15 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: ichiriac # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..9dcd15831 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: +- package-ecosystem: npm + directory: "/" + schedule: + interval: daily + time: "04:00" + open-pull-requests-limit: 10 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..debaac9da --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,54 @@ +name: Node CI + +on: [push, pull_request] + +jobs: + test: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest] + node-version: [18.x, 20.x, 22.x] + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + + - name: npm install, test + run: | + yarn + yarn test + + - name: type check + run: | + yarn build-types + [ $(git diff types.d.ts | wc -l) -gt 0 ] && echo 'Diff exists in types.d.ts. Please change jsdoc.' && exit 1 + tsc --noEmit types.d.ts + + - name: install valgrind + run: sudo apt-get install -y valgrind + + - name: benchmark + run: python cachegrind.py node test/benchmark2.js > output.txt + + - name: Download previous benchmark result + uses: actions/cache@v1 + with: + path: ./cache + key: ${{ runner.os }}-${{matrix.node-version}}-benchmark + + - name: Store benchmark result + uses: benchmark-action/github-action-benchmark@v1 + with: + tool: "customSmallerIsBetter" + output-file-path: output.txt + external-data-json-path: ./cache/benchmark-data.json + alert-threshold: "105%" + fail-on-alert: true + env: + CI: true diff --git a/.gitignore b/.gitignore index a0cd23ec8..e376a463b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,10 @@ /npm-debug.log /nbproject /coverage +/.vscode +/vendor +/dist +*.swp +composer.lock +composer.json +.idea/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 000000000..a742ac63a --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +yarpm test diff --git a/.jsdoc.json b/.jsdoc.json new file mode 100644 index 000000000..42435962f --- /dev/null +++ b/.jsdoc.json @@ -0,0 +1,33 @@ +{ + "tags": { + "allowUnknownTags": true + }, + "source": { + "include": ["src"], + "includePattern": ".+\\.js(doc|x)?$", + "excludePattern": "(^|\\/|\\\\)_" + }, + "plugins": ["plugins/markdown"], + "markdown": { + "idInHeadings": true + }, + "templates": { + "referenceTitle": "php-parser", + "cleverLinks": true, + "monospaceLinks": true, + "default": { + "outputSourceFiles": true + }, + "search": { + "apiKey": "d7422763b31425c3da8b220f22ff04d2", + "indexName": "glayzzle" + } + }, + "opts": { + "template": "./node_modules/jsdoc-template/", + "tutorials": "tutorials", + "destination": "docs", + "readme": "README.md", + "recurse": true + } +} diff --git a/.npmignore b/.npmignore index bd8792d5a..5ea9b176d 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,15 @@ /docs/ /test/ -/gruntfile.js +/example/ +/tutorials/ +/coverage/ +/.vscode/ +/.babelrc +/.codeclimate.yml /.coveralls.yml +/.eslintrc.js +/.eslintignore +/.jsdoc.json /.istanbul.yml /.travis.yml +/webpack.config.js \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index cc37c5494..000000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: node_js -node_js: - - '0.12' -cache: - bundler: true - directories: - - node_modules # NPM package -notifications: - email: false - webhooks: - urls: - - https://webhooks.gitter.im/e/f1d48355795bf25a8f9a - on_success: change - on_failure: always - on_start: never -script: npm run cover -after_success: cat /home/travis/build/glayzzle/php-parser/coverage/lcov.info | /home/travis/build/glayzzle/php-parser/node_modules/coveralls/bin/coveralls.js diff --git a/README.md b/README.md index a839f7275..e1e605e43 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,12 @@

php-parser

- -Coverage Status

-

This javascript library parses PHP code and convert it to AST.

+

This JavaScript library parses PHP code and converts it to an AST.

-Installation ------------- +## Installation This library is distributed with [npm](https://www.npmjs.com/package/php-parser) : @@ -17,34 +14,42 @@ This library is distributed with [npm](https://www.npmjs.com/package/php-parser) npm install php-parser --save ``` -Usage ------ +## Usage ```js // initialize the php parser factory class -var engine = require('php-parser'); +const fs = require("fs"); +const path = require("path"); +const engine = require("php-parser"); + // initialize a new parser instance -var parser = new engine({ +const parser = new engine({ // some options : parser: { - extractDoc: true + extractDoc: true, + php7: true, }, ast: { - withPositions: true - } + withPositions: true, + }, }); // Retrieve the AST from the specified source -var AST = parser.parseEval('echo "Hello World";'); -// AST.kind === 'program'; -// AST.children[0].kind === 'echo'; +const eval = parser.parseEval('echo "Hello World";'); // Retrieve an array of tokens (same as php function token_get_all) -var tokens = parser.tokenGetAll(' You can add here your own project by opening an issue request. -# Misc +## License This library is released under BSD-3 license clause. - -If you want to contribute please visit this repository https://github.com/glayzzle/php-parser-dev. diff --git a/RELEASE.md b/RELEASE.md index 98b84c28f..5b0ae9b01 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,5 +1,88 @@ # Releases +## 3.0.0-prerelease.9 : (2019-08-15) +- #291 : Incorrect parsing of backslash-prefixed use declarations +- #278 : 3.0 - Confusing commentsBlocks references +- #256 : invalid ast for multiple properties +- #255 : better ast for `constant` node +- #250 : Leading comments are treated as trailing comments to the previous function body +- #248 : broken ast for `$$$$$` +- #247 : invalid ast for `silent` +- #246 : `resolution` for `classreference` doesn't work properly for `FULL_QUALIFIED_NAME` +- #242 : feat: improve `Declare` node and introduce `DeclareDirective` node +- #199 : [bug] comment location overlaps with node location for `static` node +- #192 : [bug] encapsed and staticlookup +- #180 : bug in parser with single function +- #174 : Don't output `null` for last element in `list/array` +- #128 : Don't have curly for propertylookup in offset + +## 3.0.0-prerelease.8 : (2019-01-07) + - #243 : Regression in prerelease 7 with echo + - #239 : [bug] call should be in ExpressionStatement + - #235 : invalid ast for `self` and `parent` + - #234 : regression with parens in `3.0.0-prerelease.7` + - #230 : `resolvePrecedence` break location for `bin` nodes + - #207 : [feature] use `identifier` for `class/interface/trait` name + - #202 : [bug] comment position in lookup + - #194 : [feature] implement trailingComments on nodes + - #185 : [bug] parens and staticlookup + - #182 : strange with parens, staticlookup and offsetlookup + - #181 : strange with parens and unary + - #172 : cast precedence + - #167 : staticlookup is broken with curly + +## 3.0.0-prerelease.7 : (2018-11-10) + - #220 : regression in `rc-6` + - #210 : [bug] invalid ast for `const` enhancement + - #204 : [bug] invalid start offset encapsed AST bug + - #201 : [bug] curly in staticlookup bug + - #175 : impossible detect curly in `encapsed` AST enhancement + - #165 : declare doesn't support inline nodes investigating + +Many thanks to @evilebottnawi for his help + +## 3.0.0-prerelease.6 : (2018-10-21) + - impl #196 : identifier for function/method name + - fix #183 : `static` parsed as constref + - fix #188 : `constref` vs `identifier` + - fix #113 : Unhandled native identifiers + +## 3.0.0-alpha3 : (2018-08-15) + - fix #168 : End location of `if` without semicolon + - impl #147 : Node informations about Binary and unicode strings + - impl #83 : Adding full support for PHP 7.2 + - fix #122 : Detect foreach bad syntax + - impl #152 : Improve tests with JEST + - fix #164 : Fixing some location issues (partial) + +## 3.0.0-alpha2 : (2018-04-14) + - fix #137 : Bug with parsing `list` + - fix #149 : Binary cast: isDoubleQuote incorrect + - fix #150 : strange ast with list + - fix #151 : Declare inside if + +## 3.0.0-alpha1 : (2018-04-11) + - https://github.com/glayzzle/php-parser/milestone/10 + - many fixes + - changed the way comments are handled + - add a new `raw` property on some nodes + +## 2.2.0 : (2017-12-27) +- Impl #108 : add an option to disable PHP7 support +- Fix #107 : fix T_DOUBLE_COLON handler +- Fix #106 : infinite loops from lexer (unput) +- Fix #105 : T_DOLLAR_OPEN_CURLY_BRACES handles now expressions +- PR #102 : Normalize the way type casts are defined +- Fix #103 : Fix critical cast to null confusion + +## 2.1.0 : (2017-11-01) +- Impl #91 & #92 : Functions support reserved names (PHP7) +- Fix #89 : parsing methods can use Buffers or Strings + +## 2.0.7 : (2017-09-03) +- Fix #86 : bug on Object properties usage in PHP like `__proto__`, or `constructor` +- Fix #84 : remove null statements from bodies + ## 2.0.6 : (2017-07-16) - Fix precedence between bin, retif, unary diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 000000000..53fb44a4d --- /dev/null +++ b/babel.config.js @@ -0,0 +1,11 @@ +module.exports = function (api) { + api.cache(true); + + const presets = ["@babel/preset-env"]; + const plugins = []; + + return { + presets, + plugins, + }; +}; diff --git a/cachegrind.py b/cachegrind.py new file mode 100644 index 000000000..ce1c38024 --- /dev/null +++ b/cachegrind.py @@ -0,0 +1,137 @@ +""" +Proof-of-concept: run_with_cachegrind a program under Cachegrind, combining all the various +metrics into one single performance metric. + +Requires Python 3. + +License: https://opensource.org/licenses/MIT + +## Features + +* Disables ASLR. +* Sets consistent cache sizes. +* Calculates a combined performance metric. + +For more information see the detailed write up at: + +https://pythonspeed.com/articles/consistent-benchmarking-in-ci/ + +## Usage + +This script has no compatibility guarnatees, I recommend copying it into your +repository. To use: + +$ python3 cachegrind.py ./yourprogram --yourparam=yourvalues + +If you're benchmarking Python, make sure to set PYTHONHASHSEED to a fixed value +(e.g. `export PYTHONHASHSEED=1234`). Other languages may have similar +requirements to reduce variability. + +The last line printed will be a combined performance metric, but you can tweak +the script to extract more info, or use it as a library. + +Copyright © 2020, Hyphenated Enterprises LLC. +""" + +import json +from typing import List, Dict +from subprocess import check_call, check_output +import sys +from tempfile import NamedTemporaryFile + +ARCH = check_output(["uname", "-m"]).strip() + + +def run_with_cachegrind(args_list: List[str]) -> Dict[str, int]: + """ + Run the the given program and arguments under Cachegrind, parse the + Cachegrind specs. + + For now we just ignore program output, and in general this is not robust. + """ + temp_file = NamedTemporaryFile("r+") + check_call([ + # Disable ASLR: + "setarch", + ARCH, + "-R", + "valgrind", + "--tool=cachegrind", + # Set some reasonable L1 and LL values, based on Haswell. You can set + # your own, important part is that they are consistent across runs, + # instead of the default of copying from the current machine. + "--I1=32768,8,64", + "--D1=32768,8,64", + "--LL=8388608,16,64", + "--cachegrind-out-file=" + temp_file.name, + ] + args_list) + return parse_cachegrind_output(temp_file) + + +def parse_cachegrind_output(temp_file): + # Parse the output file: + lines = iter(temp_file) + for line in lines: + if line.startswith("events: "): + header = line[len("events: "):].strip() + break + for line in lines: + last_line = line + assert last_line.startswith("summary: ") + last_line = last_line[len("summary:"):].strip() + return dict(zip(header.split(), [int(i) for i in last_line.split()])) + + +def get_counts(cg_results: Dict[str, int]) -> Dict[str, int]: + """ + Given the result of run_with_cachegrind(), figure out the parameters we will use for final + estimate. + + We pretend there's no L2 since Cachegrind doesn't currently support it. + + Caveats: we're not including time to process instructions, only time to + access instruction cache(s), so we're assuming time to fetch and run_with_cachegrind + instruction is the same as time to retrieve data if they're both to L1 + cache. + """ + result = {} + d = cg_results + + ram_hits = d["DLmr"] + d["DLmw"] + d["ILmr"] + + l3_hits = d["I1mr"] + d["D1mw"] + d["D1mr"] - ram_hits + + total_memory_rw = d["Ir"] + d["Dr"] + d["Dw"] + l1_hits = total_memory_rw - l3_hits - ram_hits + assert total_memory_rw == l1_hits + l3_hits + ram_hits + + result["l1"] = l1_hits + result["l3"] = l3_hits + result["ram"] = ram_hits + + return result + + +def combined_instruction_estimate(counts: Dict[str, int]) -> int: + """ + Given the result of run_with_cachegrind(), return estimate of total time to run_with_cachegrind. + + Multipliers were determined empirically, but some research suggests they're + a reasonable approximation for cache time ratios. L3 is probably too low, + but then we're not simulating L2... + """ + return counts["l1"] + (5 * counts["l3"]) + (35 * counts["ram"]) + + +def github_action_benchmark_json(value): + return json.dumps([ + { + "name": "score", + "unit": "", + "value": value, + } + ]) + + +if __name__ == "__main__": + print(github_action_benchmark_json(combined_instruction_estimate(get_counts(run_with_cachegrind(sys.argv[1:]))))) diff --git a/dist/php-parser.js b/dist/php-parser.js deleted file mode 100644 index 8475e6faf..000000000 --- a/dist/php-parser.js +++ /dev/null @@ -1,8533 +0,0 @@ -/*! php-parser - BSD3 License - 2017-07-16 */ - -require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],2:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://gla*yzzle.com - */ - -var Location = require('./ast/location'); -var Position = require('./ast/position'); - -/** - * ## Class hierarchy - * - * - [Location](#location) - * - [Position](#position) - * - [Node](#node) - * - [Identifier](#identifier) - * - [TraitUse](#traituse) - * - [TraitAlias](#traitalias) - * - [TraitPrecedence](#traitprecedence) - * - [Entry](#entry) - * - [Case](#case) - * - [Label](#label) - * - [Doc](#doc) - * - [Error](#error) - * - [Expression](#expression) - * - [Array](#array) - * - [Variable](#variable) - * - [Variadic](#variadic) - * - [ConstRef](#constref) - * - [Yield](#yield) - * - [YieldFrom](#yieldfrom) - * - [Lookup](#lookup) - * - [PropertyLookup](#propertylookup) - * - [StaticLookup](#staticlookup) - * - [OffsetLookup](#offsetlookup) - * - [Operation](#operation) - * - [Pre](#pre) - * - [Post](#post) - * - [Bin](#bin) - * - [Parenthesis](#parenthesis) - * - [Unary](#unary) - * - [Cast](#cast) - * - [Literal](#literal) - * - [Boolean](#boolean) - * - [String](#string) - * - [Number](#number) - * - [Inline](#inline) - * - [Magic](#magic) - * - [Nowdoc](#nowdoc) - * - [Encapsed](#encapsed) - * - [Statement](#statement) - * - [Eval](#eval) - * - [Exit](#exit) - * - [Halt](#halt) - * - [Clone](#clone) - * - [Declare](#declare) - * - [Global](#global) - * - [Static](#static) - * - [Include](#include) - * - [Assign](#assign) - * - [RetIf](#retif) - * - [If](#if) - * - [Do](#do) - * - [While](#while) - * - [For](#for) - * - [Foreach](#foreach) - * - [Switch](#switch) - * - [Goto](#goto) - * - [Silent](#silent) - * - [Try](#try) - * - [Catch](#catch) - * - [Throw](#throw) - * - [Call](#call) - * - [Closure](#closure) - * - [New](#new) - * - [UseGroup](#usegroup) - * - [UseItem](#useitem) - * - [Block](#block) - * - [Program](#program) - * - [Namespace](#namespace) - * - [Sys](#sys) - * - [Echo](#echo) - * - [List](#list) - * - [Print](#print) - * - [Isset](#isset) - * - [Unset](#unset) - * - [Empty](#empty) - * - [Declaration](#declaration) - * - [Class](#class) - * - [Interface](#interface) - * - [Trait](#trait) - * - [Constant](#constant) - * - [ClassConstant](#classconstant) - * - [Function](#function) - * - [Method](#method) - * - [Parameter](#parameter) - * - [Property](#property) - * --- - */ - -/** - * The AST builder class - * @constructor AST - * @property {Boolean} withPositions - Should locate any node (by default false) - * @property {Boolean} withSource - Should extract the node original code (by default false) - */ -var AST = function(withPositions, withSource) { - this.withPositions = withPositions; - this.withSource = withSource; -}; - -/** - * Create a position node from specified parser - * including it's lexer current state - * @param {Parser} - * @return {Position} - * @private - */ -AST.prototype.position = function(parser) { - return new Position( - parser.lexer.yylloc.first_line, - parser.lexer.yylloc.first_column, - parser.lexer.yylloc.first_offset - ); -}; - - -// operators in ascending order of precedence -AST.precedence = {}; -var binOperatorsPrecedence = [ - ['or'], - ['xor'], - ['and'], - ['='], - ['?'], - ['??'], - ['||'], - ['&&'], - ['|'], - ['^'], - ['&'], - ['==', '!=', '===', '!==', /* '<>', */ '<=>'], - ['<', '<=', '>', '>='], - ['<<', '>>'], - ['+', '-', '.'], - ['*', '/', '%'], - ['!'], - ['instanceof'], - // TODO: typecasts - // TODO: [ (array) - // TODO: clone, new -].forEach(function (list, index) { - list.forEach(function (operator) { - AST.precedence[operator] = index + 1; - }); -}); - - -/** - * Check and fix precence, by default using right - */ -AST.prototype.resolvePrecedence = function(result) { - var buffer; - // handling precendence - if (result.kind === 'bin') { - if (result.right) { - if (result.right.kind === 'bin') { - var lLevel = AST.precedence[result.type]; - var rLevel = AST.precedence[result.right.type]; - if (lLevel && rLevel && rLevel <= lLevel) { - // https://github.com/glayzzle/php-parser/issues/79 - // shift precedence - buffer = result.right; - result.right = result.right.left; - buffer.left = this.resolvePrecedence(result); - result = buffer; - } - } else if (result.right.kind === 'retif') { - var lLevel = AST.precedence[result.type]; - var rLevel = AST.precedence['?']; - if (lLevel && rLevel && rLevel <= lLevel) { - buffer = result.right; - result.right = result.right.test; - buffer.test = this.resolvePrecedence(result); - result = buffer; - } - } - } - } else if (result.kind === 'unary') { - // https://github.com/glayzzle/php-parser/issues/75 - if (result.what) { - // unary precedence is allways lower - if (result.what.kind === 'bin') { - buffer = result.what; - result.what = result.what.left; - buffer.left = this.resolvePrecedence(result); - result = buffer; - } else if (result.what.kind === 'retif') { - buffer = result.what; - result.what = result.what.test; - buffer.test = this.resolvePrecedence(result); - result = buffer; - } - } - } else if (result.kind === 'retif') { - // https://github.com/glayzzle/php-parser/issues/77 - if (result.falseExpr && result.falseExpr.kind === 'retif') { - buffer = result.falseExpr; - result.falseExpr = buffer.test; - buffer.test = this.resolvePrecedence(result); - result = buffer; - } - } else if (result.kind === 'assign') { - // https://github.com/glayzzle/php-parser/issues/81 - if (result.right && result.right.kind === 'bin') { - var lLevel = AST.precedence['=']; - var rLevel = AST.precedence[result.right.type]; - // only shifts with and, xor, or - if (lLevel && rLevel && rLevel < lLevel) { - buffer = result.right; - result.right = result.right.left; - buffer.left = result; - result = buffer; - } - } - } - return result; -}; - -/** - * Prepares an AST node - * @param {String|null} kind - Defines the node type - * (if null, the kind must be passed at the function call) - * @param {Parser} parser - The parser instance (use for extracting locations) - * @return {Function} - */ -AST.prototype.prepare = function(kind, parser) { - var start = null; - if (this.withPositions || this.withSource) { - start = this.position(parser); - } - var self = this; - // returns the node - return function() { - var location = null; - var args = Array.prototype.slice.call(arguments); - if (self.withPositions || self.withSource) { - var src = null; - if (self.withSource) { - src = parser.lexer._input.substring( - start.offset, - parser.lexer.yylloc.prev_offset - ); - } - if (self.withPositions) { - location = new Location(src, start, new Position( - parser.lexer.yylloc.prev_line, - parser.lexer.yylloc.prev_column, - parser.lexer.yylloc.prev_offset - )); - } else { - location = new Location(src, null, null); - } - // last argument is allways the location - args.push(location); - } - // handle lazy kind definitions - if (!kind) { - kind = args.shift(); - } - // build the object - var node = self[kind]; - if (typeof node !== 'function') { - throw new Error('Undefined node "'+kind+'"'); - } - var result = Object.create(node.prototype); - node.apply(result, args); - return self.resolvePrecedence(result); - }; -}; - -// Define all AST nodes -[ - require('./ast/array'), - require('./ast/assign'), - require('./ast/bin'), - require('./ast/block'), - require('./ast/boolean'), - require('./ast/break'), - require('./ast/call'), - require('./ast/case'), - require('./ast/cast'), - require('./ast/catch'), - require('./ast/class'), - require('./ast/classconstant'), - require('./ast/clone'), - require('./ast/closure'), - require('./ast/constant'), - require('./ast/constref'), - require('./ast/continue'), - require('./ast/declaration'), - require('./ast/declare'), - require('./ast/do'), - require('./ast/doc'), - require('./ast/echo'), - require('./ast/empty'), - require('./ast/encapsed'), - require('./ast/entry'), - require('./ast/error'), - require('./ast/eval'), - require('./ast/exit'), - require('./ast/expression'), - require('./ast/for'), - require('./ast/foreach'), - require('./ast/function'), - require('./ast/global'), - require('./ast/goto'), - require('./ast/halt'), - require('./ast/identifier'), - require('./ast/if'), - require('./ast/include'), - require('./ast/inline'), - require('./ast/interface'), - require('./ast/isset'), - require('./ast/label'), - require('./ast/list'), - require('./ast/literal'), - require('./ast/lookup'), - require('./ast/magic'), - require('./ast/method'), - require('./ast/namespace'), - require('./ast/new'), - require('./ast/node'), - require('./ast/nowdoc'), - require('./ast/number'), - require('./ast/offsetlookup'), - require('./ast/operation'), - require('./ast/parameter'), - require('./ast/parenthesis'), - require('./ast/post'), - require('./ast/pre'), - require('./ast/print'), - require('./ast/program'), - require('./ast/property'), - require('./ast/propertylookup'), - require('./ast/retif'), - require('./ast/return'), - require('./ast/silent'), - require('./ast/statement'), - require('./ast/static'), - require('./ast/staticlookup'), - require('./ast/string'), - require('./ast/switch'), - require('./ast/sys'), - require('./ast/throw'), - require('./ast/trait'), - require('./ast/traitalias'), - require('./ast/traitprecedence'), - require('./ast/traituse'), - require('./ast/try'), - require('./ast/unary'), - require('./ast/unset'), - require('./ast/usegroup'), - require('./ast/useitem'), - require('./ast/variable'), - require('./ast/variadic'), - require('./ast/while'), - require('./ast/yield'), - require('./ast/yieldfrom') -].forEach(function (ctor) { - var kind = ctor.prototype.constructor.name.toLowerCase(); - if (kind[0] === '_') kind = kind.substring(1); - AST.prototype[kind] = ctor; -}); - -module.exports = AST; - -},{"./ast/array":3,"./ast/assign":4,"./ast/bin":5,"./ast/block":6,"./ast/boolean":7,"./ast/break":8,"./ast/call":9,"./ast/case":10,"./ast/cast":11,"./ast/catch":12,"./ast/class":13,"./ast/classconstant":14,"./ast/clone":15,"./ast/closure":16,"./ast/constant":17,"./ast/constref":18,"./ast/continue":19,"./ast/declaration":20,"./ast/declare":21,"./ast/do":22,"./ast/doc":23,"./ast/echo":24,"./ast/empty":25,"./ast/encapsed":26,"./ast/entry":27,"./ast/error":28,"./ast/eval":29,"./ast/exit":30,"./ast/expression":31,"./ast/for":32,"./ast/foreach":33,"./ast/function":34,"./ast/global":35,"./ast/goto":36,"./ast/halt":37,"./ast/identifier":38,"./ast/if":39,"./ast/include":40,"./ast/inline":41,"./ast/interface":42,"./ast/isset":43,"./ast/label":44,"./ast/list":45,"./ast/literal":46,"./ast/location":47,"./ast/lookup":48,"./ast/magic":49,"./ast/method":50,"./ast/namespace":51,"./ast/new":52,"./ast/node":53,"./ast/nowdoc":54,"./ast/number":55,"./ast/offsetlookup":56,"./ast/operation":57,"./ast/parameter":58,"./ast/parenthesis":59,"./ast/position":60,"./ast/post":61,"./ast/pre":62,"./ast/print":63,"./ast/program":64,"./ast/property":65,"./ast/propertylookup":66,"./ast/retif":67,"./ast/return":68,"./ast/silent":69,"./ast/statement":70,"./ast/static":71,"./ast/staticlookup":72,"./ast/string":73,"./ast/switch":74,"./ast/sys":75,"./ast/throw":76,"./ast/trait":77,"./ast/traitalias":78,"./ast/traitprecedence":79,"./ast/traituse":80,"./ast/try":81,"./ast/unary":82,"./ast/unset":83,"./ast/usegroup":84,"./ast/useitem":85,"./ast/variable":86,"./ast/variadic":87,"./ast/while":88,"./ast/yield":89,"./ast/yieldfrom":90}],3:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Expr = require('./expression'); -var KIND = 'array'; - -/** - * Defines an array structure - * @constructor Array - * @example - * // PHP code : - * [1, 'foo' => 'bar', 3] - * - * // AST structure : - * { - * "kind": "array", - * "shortForm": true - * "items": [{ - * "kind": "entry", - * "key": null, - * "value": {"kind": "number", "value": "1"} - * }, { - * "kind": "entry", - * "key": {"kind": "string", "value": "foo", "isDoubleQuote": false}, - * "value": {"kind": "string", "value": "bar", "isDoubleQuote": false} - * }, { - * "kind": "entry", - * "key": null, - * "value": {"kind": "number", "value": "3"} - * }] - * } - * @extends {Expression} - * @property {Entry[]} items List of array items - * @property {boolean} shortForm Indicate if the short array syntax is used, ex `[]` instead `array()` - */ -var Array = Expr.extends(function Array(shortForm, items, location) { - Expr.apply(this, [KIND, location]); - this.items = items; - this.shortForm = shortForm; -}); - -module.exports = Array; - -},{"./expression":31}],4:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Statement = require('./statement'); -var KIND = 'assign'; - -/** - * Assigns a value to the specified target - * @constructor Assign - * @extends {Statement} - * @property {Expression} left - * @property {Expression} right - * @property {String} operator - */ -var Assign = Statement.extends(function Assign(left, right, operator, location) { - Statement.apply(this, [KIND, location]); - this.operator = operator; - this.left = left; - this.right = right; -}); - -module.exports = Assign; - -},{"./statement":70}],5:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Operation = require('./operation'); -var KIND = 'bin'; -/** - * Binary operations - * @constructor Bin - * @extends {Operation} - * @property {String} type - * @property {Expression} left - * @property {Expression} right - */ -var Bin = Operation.extends(function Bin(type, left, right, location) { - Operation.apply(this, [KIND, location]); - this.type = type; - this.left = left; - this.right = right; -}); - -module.exports = Bin; - -},{"./operation":57}],6:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Statement = require('./statement'); -var KIND = 'block'; - -/** - * A block statement, i.e., a sequence of statements surrounded by braces. - * @constructor Block - * @extends {Statement} - * @property {Node[]} children - */ -var Block = Statement.extends(function Block(kind, children, location) { - Statement.apply(this, [kind || KIND, location]); - this.children = children; -}); - -module.exports = Block; - -},{"./statement":70}],7:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Literal = require('./literal'); -var KIND = 'boolean'; - -/** - * Defines a boolean value (true/false) - * @constructor Boolean - * @extends {Literal} - */ -var Boolean = Literal.extends(function Boolean(value, location) { - Literal.apply(this, [KIND, value, location]); -}); - -module.exports = Boolean; - -},{"./literal":46}],8:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Node = require('./node'); -var KIND = 'break'; - -/** - * A break statement - * @constructor Break - * @extends {Node} - * @property {Number|Null} level - */ -var Break = Node.extends(function Break(level, location) { - Node.apply(this, [KIND, location]); - this.level = level; -}); - -module.exports = Break; - -},{"./node":53}],9:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'call'; - -/** - * Executes a call statement - * @constructor Call - * @extends {Statement} - * @property {Identifier|Variable|??} what - * @property {Arguments[]} arguments - */ -var Call = Statement.extends(function Call(what, args, location) { - Statement.apply(this, [KIND, location]); - this.what = what; - this.arguments = args; -}); - -module.exports = Call; - -},{"./statement":70}],10:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Node = require('./node'); -var KIND = 'case'; - -/** - * A switch case statement - * @constructor Case - * @extends {Node} - * @property {Expression|null} test - if null, means that the default case - * @property {Block|null} body - */ -var Case = Node.extends(function Case(test, body, location) { - Node.apply(this, [KIND, location]); - this.test = test; - this.body = body; -}); - -module.exports = Case; - -},{"./node":53}],11:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Operation = require('./operation'); -var KIND = 'cast'; - -/** - * Binary operations - * @constructor Cast - * @extends {Operation} - * @property {String} type - * @property {Expression} what - */ -var Cast = Operation.extends(function Cast(type, what, location) { - Operation.apply(this, [KIND, location]); - this.type = type; - this.what = what; -}); - -module.exports = Cast; - -},{"./operation":57}],12:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'catch'; - -/** - * Defines a catch statement - * @constructor Catch - * @extends {Statement} - * @property {Identifier[]} what - * @property {Variable} variable - * @property {Statement} body - * @see http://php.net/manual/en/language.exceptions.php - */ -var Catch = Statement.extends(function Catch(body, what, variable, location) { - Statement.apply(this, [KIND, location]); - this.body = body; - this.what = what; - this.variable = variable; -}); - -module.exports = Catch; - -},{"./statement":70}],13:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Declaration = require('./declaration'); -var KIND = 'class'; - - -/** - * A class definition - * @constructor Class - * @extends {Declaration} - * @property {Identifier|null} extends - * @property {Identifier[]} implements - * @property {Declaration[]} body - * @property {boolean} isAnonymous - * @property {boolean} isAbstract - * @property {boolean} isFinal - */ -var Class = Declaration.extends(function Class(name, ext, impl, body, flags, location) { - Declaration.apply(this, [KIND, name, location]); - this.isAnonymous = name ? false : true; - this.extends = ext; - this.implements = impl; - this.body = body; - this.parseFlags(flags); -}); - -module.exports = Class; - -},{"./declaration":20}],14:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Constant = require('./constant'); -var KIND = 'classconstant'; - -/** - * Defines a class/interface/trait constant - * @constructor ClassConstant - * @extends {Constant} - * @property {boolean} isStatic - * @property {string} visibility - */ -var ClassConstant = Constant.extends(function ClassConstant(name, value, flags, location) { - Constant.apply(this, [name, value, location]); - this.kind = KIND; - this.parseFlags(flags); -}); - -module.exports = ClassConstant; - -},{"./constant":17}],15:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Statement = require('./statement'); -var KIND = 'clone'; - -/** - * Defines a clone call - * @constructor Clone - * @extends {Statement} - * @property {Expression} what - */ -var Clone = Statement.extends(function Clone(what, location) { - Statement.apply(this, [KIND, location]); - this.what = what; -}); - -module.exports = Clone; - -},{"./statement":70}],16:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Statement = require('./statement'); -var KIND = 'closure'; - -/** - * Defines a closure - * @constructor Closure - * @extends {Statement} - * @property {Parameter[]} arguments - * @property {Variable[]} uses - * @property {Identifier} type - * @property {boolean} byref - * @property {boolean} nullable - * @property {Block|null} body - * @property {boolean} isStatic - */ -var Closure = Statement.extends(function Closure(args, byref, uses, type, nullable, isStatic, location) { - Statement.apply(this, [KIND, location]); - this.uses = uses; - this.arguments = args; - this.byref = byref; - this.type = type; - this.nullable = nullable; - this.isStatic = isStatic || false; - this.body = null; -}); - -module.exports = Closure; - -},{"./statement":70}],17:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Declaration = require('./declaration'); -var KIND = 'constant'; - -/** - * Defines a namespace constant - * @constructor Constant - * @extends {Declaration} - * @property {Node|null} value - */ -var Constant = Declaration.extends(function Constant(name, value, location) { - Declaration.apply(this, [KIND, name, location]); - this.value = value; -}); - -module.exports = Constant; - -},{"./declaration":20}],18:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Expr = require('./expression'); -var KIND = 'constref'; - -/** - * A constant reference - * @constructor ConstRef - * @extends {Expression} - * @property {String|Node} name - */ -var ConstRef = Expr.extends(function ConstRef(identifier, location) { - Expr.apply(this, [KIND, location]); - this.name = identifier; -}); - -module.exports = ConstRef; - -},{"./expression":31}],19:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Node = require('./node'); -var KIND = 'continue'; - -/** - * A continue statement - * @constructor Continue - * @extends {Node} - * @property {Number|Null} level - */ -var Continue = Node.extends(function Continue(level, location) { - Node.apply(this, [KIND, location]); - this.level = level; -}); - -module.exports = Continue; - -},{"./node":53}],20:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Statement = require('./statement'); -var KIND = 'declaration'; - -var IS_PUBLIC = 'public'; -var IS_PROTECTED = 'protected'; -var IS_PRIVATE = 'private'; - -/** - * A declaration statement (function, class, interface...) - * @constructor Declaration - * @extends {Statement} - * @property {string} name - */ -var Declaration = Statement.extends(function Declaration(kind, name, location) { - Statement.apply(this, [kind || KIND, location]); - this.name = name; -}); - -/** - * Generic flags parser - * @param {Integer[]} flags - * @return {void} - */ -Declaration.prototype.parseFlags = function(flags) { - this.isAbstract = flags[2] === 1; - this.isFinal = flags[2] === 2; - if (this.kind !== 'class') { - if (flags[0] === 0) { - this.visibility = IS_PUBLIC; - } else if (flags[0] === 1) { - this.visibility = IS_PROTECTED; - } else if (flags[0] === 2) { - this.visibility = IS_PRIVATE; - } - this.isStatic = flags[1] === 1; - } -}; - -module.exports = Declaration; - -},{"./statement":70}],21:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Block = require('./block'); -var KIND = 'declare'; - -/** - * The declare construct is used to set execution directives for a block of code - * @constructor Declare - * @extends {Block} - * @property {Expression[]} what - * @property {String} mode - * @see http://php.net/manual/en/control-structures.declare.php - */ -var Declare = Block.extends(function Declare(what, body, mode, location) { - Block.apply(this, [KIND, body, location]); - this.what = what; - this.mode = mode; -}); - - -/** - * The node is declared as a short tag syntax : - * ```php - * bar_$baz; - * ``` - * @constant {String} TYPE_OFFSET - `offset` - */ -Encapsed.TYPE_OFFSET = 'offset'; - - -module.exports = Encapsed; - -},{"./literal":46}],27:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Node = require('./node'); -var KIND = 'entry'; - -/** - * An array entry - see [Array](#array) - * @constructor Entry - * @extends {Node} - * @property {Node|null} key The entry key/offset - * @property {Node} value The entry value - */ -var Entry = Node.extends(function Entry(key, value, location) { - Node.apply(this, [KIND, location]); - this.key = key; - this.value = value; -}); - -module.exports = Entry; - -},{"./node":53}],28:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Node = require('./node'); -var KIND = 'error'; - - -/** - * Defines an error node (used only on silentMode) - * @constructor Error - * @extends {Node} - * @property {string} message - * @property {number} line - * @property {number|string} token - * @property {string|array} expected - */ -var Error = Node.extends(function Error(message, token, line, expected, location) { - Node.apply(this, [KIND, location]); - this.message = message; - this.token = token; - this.line = line; - this.expected = expected; -}); - -module.exports = Error; - -},{"./node":53}],29:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Statement = require('./statement'); -var KIND = 'eval'; - -/** - * Defines an eval statement - * @constructor Eval - * @extends {Statement} - * @property {Node} source - */ -var Eval = Statement.extends(function Eval(source, location) { - Statement.apply(this, [KIND, location]); - this.source = source; -}); - -module.exports = Eval; - -},{"./statement":70}],30:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Statement = require('./statement'); -var KIND = 'exit'; - -/** - * Defines an exit / die call - * @constructor Exit - * @extends {Statement} - * @property {Node|null} status - */ -var Exit = Statement.extends(function Exit(status, location) { - Statement.apply(this, [KIND, location]); - this.status = status; -}); - -module.exports = Exit; - -},{"./statement":70}],31:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Node = require('./node'); -var KIND = 'expression'; - -/** - * Any expression node. Since the left-hand side of an assignment may - * be any expression in general, an expression can also be a pattern. - * @constructor Expression - * @extends {Node} - */ -var Expression = Node.extends(function Expression(kind, location) { - Node.apply(this, [kind || KIND, location]); -}); - -module.exports = Expression; - -},{"./node":53}],32:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'for'; - -/** - * Defines a for iterator - * @constructor For - * @extends {Statement} - * @property {Expression[]} init - * @property {Expression[]} test - * @property {Expression[]} increment - * @property {Statement} body - * @property {boolean} shortForm - * @see http://php.net/manual/en/control-structures.for.php - */ -var For = Statement.extends(function For(init, test, increment, body, shortForm, location) { - Statement.apply(this, [KIND, location]); - this.init = init; - this.test = test; - this.increment = increment; - this.shortForm = shortForm; - this.body = body; -}); - -module.exports = For; - -},{"./statement":70}],33:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'foreach'; - -/** - * Defines a foreach iterator - * @constructor Foreach - * @extends {Statement} - * @property {Expression} source - * @property {Expression|null} key - * @property {Expression} value - * @property {Statement} body - * @property {boolean} shortForm - * @see http://php.net/manual/en/control-structures.foreach.php - */ -var Foreach = Statement.extends(function Foreach(source, key, value, body, shortForm, location) { - Statement.apply(this, [KIND, location]); - this.source = source; - this.key = key; - this.value = value; - this.shortForm = shortForm; - this.body = body; -}); - -module.exports = Foreach; - -},{"./statement":70}],34:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Declaration = require('./declaration'); -var KIND = 'function'; - -/** - * Defines a classic function - * @constructor Function - * @extends {Declaration} - * @property {Parameter[]} arguments - * @property {Identifier} type - * @property {boolean} byref - * @property {boolean} nullable - * @property {Block|null} body - */ -var fn = Declaration.extends(function _Function(name, args, byref, type, nullable, location) { - Declaration.apply(this, [KIND, name, location]); - this.arguments = args; - this.byref = byref; - this.type = type; - this.nullable = nullable; - this.body = null; -}); -module.exports = fn; - -},{"./declaration":20}],35:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Statement = require('./statement'); -var KIND = 'global'; - -/** - * Imports a variable from the global scope - * @constructor Global - * @extends {Statement} - * @property {Variable[]} items - */ -var Global = Statement.extends(function Global(items, location) { - Statement.apply(this, [KIND, location]); - this.items = items; -}); - -module.exports = Global; - -},{"./statement":70}],36:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'goto'; - -/** - * Defines goto statement - * @constructor Goto - * @extends {Statement} - * @property {String} label - * @see {Label} - */ -var Goto = Statement.extends(function Goto(label, location) { - Statement.apply(this, [KIND, location]); - this.label = label; -}); - -module.exports = Goto; - -},{"./statement":70}],37:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'halt'; - -/** - * Halts the compiler execution - * @constructor Halt - * @extends {Statement} - * @property {String} after - String after the halt statement - * @see http://php.net/manual/en/function.halt-compiler.php - */ -var Halt = Statement.extends(function Halt(after, location) { - Statement.apply(this, [KIND, location]); - this.after = after; -}); - -module.exports = Halt; - -},{"./statement":70}],38:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Node = require('./node'); -var KIND = 'identifier'; - -/** - * Defines an identifier node - * @constructor Identifier - * @extends {Node} - * @property {string} name - * @property {string} resolution - */ -var Identifier = Node.extends(function Identifier(name, isRelative, location) { - Node.apply(this, [KIND, location]); - if (isRelative) { - this.resolution = Identifier.RELATIVE_NAME; - } else if (name.length === 1) { - this.resolution = Identifier.UNQUALIFIED_NAME; - } else if (name[0] === '') { - this.resolution = Identifier.FULL_QUALIFIED_NAME; - } else { - this.resolution = Identifier.QUALIFIED_NAME; - } - this.name = name.join('\\'); -}); - -/** - * This is an identifier without a namespace separator, such as Foo - * @constant {String} UNQUALIFIED_NAME - */ -Identifier.UNQUALIFIED_NAME = 'uqn'; -/** - * This is an identifier with a namespace separator, such as Foo\Bar - * @constant {String} QUALIFIED_NAME - */ -Identifier.QUALIFIED_NAME = 'qn'; -/** - * This is an identifier with a namespace separator that begins with - * a namespace separator, such as \Foo\Bar. The namespace \Foo is also - * a fully qualified name. - * @constant {String} FULL_QUALIFIED_NAME - */ -Identifier.FULL_QUALIFIED_NAME = 'fqn'; -/** - * This is an identifier starting with namespace, such as namespace\Foo\Bar. - * @constant {String} RELATIVE_NAME - */ -Identifier.RELATIVE_NAME = 'rn'; - - -module.exports = Identifier; - -},{"./node":53}],39:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'if'; - -/** - * Defines a if statement - * @constructor If - * @extends {Statement} - * @property {Expression} test - * @property {Block} body - * @property {Block|If|null} alternate - * @property {boolean} shortForm - */ -var If = Statement.extends(function If(test, body, alternate, shortForm, location) { - Statement.apply(this, [KIND, location]); - this.test = test; - this.body = body; - this.alternate = alternate; - this.shortForm = shortForm; -}); - -module.exports = If; - -},{"./statement":70}],40:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Statement = require('./statement'); -var KIND = 'include'; - -/** - * Defines system include call - * @constructor Include - * @extends {Statement} - * @property {Node} target - * @property {boolean} once - * @property {boolean} require - */ -var Include = Statement.extends(function Include(once, require, target, location) { - Statement.apply(this, [KIND, location]); - this.once = once; - this.require = require; - this.target = target; -}); - -module.exports = Include; - -},{"./statement":70}],41:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Literal = require('./literal'); -var KIND = 'inline'; - -/** - * Defines inline html output (treated as echo output) - * @constructor Inline - * @extends {Literal} - */ -var Inline = Literal.extends(function Inline(value, location) { - Literal.apply(this, [KIND, value, location]); -}); - -module.exports = Inline; - -},{"./literal":46}],42:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Declaration = require('./declaration'); -var KIND = 'interface'; - - -/** - * An interface definition - * @constructor Interface - * @extends {Declaration} - * @property {Identifier[]} extends - * @property {Declaration[]} body - */ -var Interface = Declaration.extends(function Interface(name, ext, body, location) { - Declaration.apply(this, [KIND, name, location]); - this.extends = ext; - this.body = body; -}); - -module.exports = Interface; - -},{"./declaration":20}],43:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Sys = require('./sys'); -var KIND = 'isset'; - -/** - * Defines an isset call - * @constructor Isset - * @extends {Sys} - */ -var Isset = Sys.extends(function Isset(args, location) { - Sys.apply(this, [KIND, args, location]); -}); - -module.exports = Isset; - -},{"./sys":75}],44:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Node = require('./node'); -var KIND = 'label'; - -/** - * A label statement (referenced by goto) - * @constructor Label - * @extends {Node} - * @property {String} name - */ -var Label = Node.extends(function Label(name, location) { - Node.apply(this, [KIND, location]); - this.name = name; -}); - -module.exports = Label; - -},{"./node":53}],45:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Sys = require('./sys'); -var KIND = 'list'; - -/** - * Defines list assignment - * @constructor List - * @extends {Sys} - */ -var List = Sys.extends(function List(args, location) { - Sys.apply(this, [KIND, args, location]); -}); - -module.exports = List; - -},{"./sys":75}],46:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Expr = require('./expression'); -var KIND = 'literal'; - -/** - * Defines an array structure - * @constructor Literal - * @extends {Expression} - * @property {Node|string|number|boolean|null} value - */ -var Literal = Expr.extends(function Literal(kind, value, location) { - Expr.apply(this, [kind || KIND, location]); - this.value = value; -}); - -module.exports = Literal; - -},{"./expression":31}],47:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -/** - * Defines the location of the node (with it's source contents as string) - * @constructor Location - * @property {String|null} source - * @property {Position} start - * @property {Position} end - */ -var Location = function(source, start, end) { - this.source = source; - this.start = start; - this.end = end; -}; - -module.exports = Location; - -},{}],48:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Expr = require('./expression'); -var KIND = 'lookup'; - -/** - * Lookup on an offset in the specified object - * @constructor Lookup - * @extends {Expression} - * @property {Expression} what - * @property {Expression} offset - */ -var Lookup = Expr.extends(function Lookup(kind, what, offset, location) { - Expr.apply(this, [kind || KIND, location]); - this.what = what; - this.offset = offset; -}); - -module.exports = Lookup; - -},{"./expression":31}],49:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Literal = require('./literal'); -var KIND = 'magic'; - -/** - * Defines magic constant - * @constructor Magic - * @extends {Literal} - */ -var Magic = Literal.extends(function Magic(value, location) { - Literal.apply(this, [KIND, value, location]); -}); - -module.exports = Magic; - -},{"./literal":46}],50:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var fn = require('./function'); -var KIND = 'method'; - -/** - * Defines a class/interface/trait method - * @constructor Method - * @extends {Function} - * @property {boolean} isAbstract - * @property {boolean} isFinal - * @property {boolean} isStatic - * @property {string} visibility - */ -var Method = fn.extends(function Method() { - fn.apply(this, arguments); - this.kind = KIND; -}); - -module.exports = Method; - -},{"./function":34}],51:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Block = require('./block'); -var Identifier = require('./identifier'); -var KIND = 'namespace'; - -/** - * The main program node - * @constructor Namespace - * @extends {Block} - * @property {String} name - * @property {Boolean} withBrackets - */ -var Namespace = Block.extends(function Namespace(name, children, withBrackets, location) { - Block.apply(this, [KIND, children, location]); - this.name = name; - this.withBrackets = withBrackets || false; -}); - -module.exports = Namespace; - -},{"./block":6,"./identifier":38}],52:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'new'; - -/** - * Creates a new instance of the specified class - * @constructor New - * @extends {Statement} - * @property {Identifier|Variable|Class} what - * @property {Arguments[]} arguments - */ -var New = Statement.extends(function New(what, args, location) { - Statement.apply(this, [KIND, location]); - this.what = what; - this.arguments = args; -}); - -module.exports = New; - -},{"./statement":70}],53:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -/** - * A generic AST node - * @constructor Node - * @property {Location|null} loc - * @property {String} kind - */ -var Node = function Node(kind, location) { - this.kind = kind; - if(location) { - this.loc = location; - } -}; - -/** - * Helper for extending the Node class - * @param {Function} constructor - * @return {Function} - */ -Node.extends = function(constructor) { - constructor.prototype = Object.create(this.prototype); - constructor.extends = this.extends; - constructor.prototype.constructor = constructor; - return constructor; -}; - -module.exports = Node; - -},{}],54:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Literal = require('./literal'); -var KIND = 'nowdoc'; - -/** - * Defines a nowdoc string - * @constructor String - * @extends {Literal} - * @property {String} label - - */ -var Nowdoc = Literal.extends(function Nowdoc(value, label, location) { - Literal.apply(this, [KIND, value, location]); - this.label = label; -}); - -module.exports = Nowdoc; - -},{"./literal":46}],55:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Literal = require('./literal'); -var KIND = 'number'; - -/** - * Defines a numeric value - * @constructor Number - * @extends {Literal} - */ -var _Number = Literal.extends(function Number(value, location) { - Literal.apply(this, [KIND, value, location]); -}); - -module.exports = _Number; - -},{"./literal":46}],56:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Lookup = require('./lookup'); -var KIND = 'offsetlookup'; - -/** - * Lookup on an offset in an array - * @constructor OffsetLookup - * @extends {Lookup} - */ -var OffsetLookup = Lookup.extends(function OffsetLookup(what, offset, location) { - Lookup.apply(this, [KIND, what, offset, location]); -}); - -module.exports = OffsetLookup; - -},{"./lookup":48}],57:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Expr = require('./expression'); -var KIND = 'operation'; - -/** - * Defines binary operations - * @constructor Operation - * @extends {Expression} - */ -var Operation = Expr.extends(function Operation(kind, location) { - Expr.apply(this, [kind || KIND, location]); -}); - -module.exports = Operation; - -},{"./expression":31}],58:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Declaration = require('./declaration'); -var KIND = 'parameter'; - -/** - * Defines a function parameter - * @constructor Parameter - * @extends {Declaration} - * @property {Identifier|null} type - * @property {Node|null} value - * @property {boolean} byref - * @property {boolean} variadic - * @property {boolean} nullable - */ -var Parameter = Declaration.extends(function Parameter(name, type, value, isRef, isVariadic, nullable, location) { - Declaration.apply(this, [KIND, name, location]); - this.value = value; - this.type = type; - this.byref = isRef; - this.variadic = isVariadic; - this.nullable = nullable; -}); - -module.exports = Parameter; - -},{"./declaration":20}],59:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Operation = require('./operation'); -var KIND = 'parenthesis'; - -/** - * Parenthesis encapsulation `(... expr ...)` - * @constructor Parenthesis - * @extends {Operation} - * @property {Expression} inner - */ -var Parenthesis = Operation.extends(function Parenthesis(inner, location) { - Operation.apply(this, [KIND, location]); - this.inner = inner; -}); - -module.exports = Parenthesis; - -},{"./operation":57}],60:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -/** - * Each Position object consists of a line number (1-indexed) and a column number (0-indexed): - * @constructor Position - * @property {Number} line - * @property {Number} column - * @property {Number} offset - */ -var Position = function(line, column, offset) { - this.line = line; - this.column = column; - this.offset = offset; -}; - -module.exports = Position; - -},{}],61:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Operation = require('./operation'); -var KIND = 'post'; - -/** - * Defines a post operation `$i++` or `$i--` - * @constructor Post - * @extends {Operation} - * @property {String} type - * @property {Variable} what - */ -var Post = Operation.extends(function Post(type, what, location) { - Operation.apply(this, [KIND, location]); - this.type = type; - this.what = what; -}); - -module.exports = Post; - -},{"./operation":57}],62:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Operation = require('./operation'); -var KIND = 'pre'; - -/** - * Defines a pre operation `++$i` or `--$i` - * @constructor Pre - * @extends {Operation} - * @property {String} type - * @property {Variable} what - */ -var Pre = Operation.extends(function Pre(type, what, location) { - Operation.apply(this, [KIND, location]); - this.type = type; - this.what = what; -}); - -module.exports = Pre; - -},{"./operation":57}],63:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Sys = require('./sys'); -var KIND = 'print'; - -/** - * Outputs - * @constructor Print - * @extends {Sys} - */ -var Print = Sys.extends(function Print(args, location) { - Sys.apply(this, [KIND, args, location]); -}); - -module.exports = Print; - -},{"./sys":75}],64:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Block = require('./block'); -var KIND = 'program'; - -/** - * The main program node - * @constructor Program - * @extends {Block} - * @property {Error[]} errors - */ -var Program = Block.extends(function Program(children, errors, location) { - Block.apply(this, [KIND, children, location]); - this.errors = errors; -}); - -module.exports = Program; - -},{"./block":6}],65:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Declaration = require('./declaration'); -var KIND = 'property'; - -/** - * Defines a class property - * @constructor Property - * @extends {Declaration} - * @property {boolean} isFinal - * @property {boolean} isStatic - * @property {string} visibility - * @property {Node|null} value - */ -var Property = Declaration.extends(function Property(name, value, flags, location) { - Declaration.apply(this, [KIND, name, location]); - this.value = value; - this.parseFlags(flags); -}); - -module.exports = Property; - -},{"./declaration":20}],66:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Lookup = require('./lookup'); -var KIND = 'propertylookup'; - -/** - * Lookup to an object property - * @constructor PropertyLookup - * @extends {Lookup} - */ -var PropertyLookup = Lookup.extends(function PropertyLookup(what, offset, location) { - Lookup.apply(this, [KIND, what, offset, location]); -}); - -module.exports = PropertyLookup; - -},{"./lookup":48}],67:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'retif'; - -/** - * Defines a short if statement that returns a value - * @constructor RetIf - * @extends {Statement} - * @property {Expression} test - * @property {Expression} trueExpr - * @property {Expression} falseExpr - */ -var RetIf = Statement.extends(function RetIf(test, trueExpr, falseExpr, location) { - Statement.apply(this, [KIND, location]); - this.test = test; - this.trueExpr = trueExpr; - this.falseExpr = falseExpr; -}); - -module.exports = RetIf; - -},{"./statement":70}],68:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Node = require('./node'); -var KIND = 'return'; - -/** - * A continue statement - * @constructor Return - * @extends {Node} - * @property {Expression|null} expr - */ -var Return = Node.extends(function Return(expr, location) { - Node.apply(this, [KIND, location]); - this.expr = expr; -}); - -module.exports = Return; - -},{"./node":53}],69:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'silent'; - -/** - * Avoids to show/log warnings & notices from the inner expression - * @constructor Silent - * @extends {Statement} - * @property {Expression} expr - */ -var Silent = Statement.extends(function Silent(expr, location) { - Statement.apply(this, [KIND, location]); - this.expr = expr; -}); - -module.exports = Silent; - -},{"./statement":70}],70:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Node = require('./node'); -var KIND = 'statement'; - -/** - * Any statement. - * @constructor Statement - * @extends {Node} - */ -var Statement = Node.extends(function Statement(kind, location) { - Node.apply(this, [kind || KIND, location]); -}); - -module.exports = Statement; - -},{"./node":53}],71:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Statement = require('./statement'); -var KIND = 'static'; - -/** - * Declares a static variable into the current scope - * @constructor Static - * @extends {Statement} - * @property {Variable[]|Assign[]} items - */ -var Static = Statement.extends(function Static(items, location) { - Statement.apply(this, [KIND, location]); - this.items = items; -}); - -module.exports = Static; - -},{"./statement":70}],72:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Lookup = require('./lookup'); -var KIND = 'staticlookup'; - -/** - * Lookup to a static property - * @constructor StaticLookup - * @extends {Lookup} - */ -var StaticLookup = Lookup.extends(function StaticLookup(what, offset, location) { - Lookup.apply(this, [KIND, what, offset, location]); -}); - -module.exports = StaticLookup; - -},{"./lookup":48}],73:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Literal = require('./literal'); -var KIND = 'string'; - -/** - * Defines a string (simple ou double quoted) - chars are already escaped - * @constructor String - * @extends {Literal} - * @property {boolean} isDoubleQuote - * @see {Encapsed} - */ -var String = Literal.extends(function String(isDoubleQuote, value, location) { - Literal.apply(this, [KIND, value, location]); - this.isDoubleQuote = isDoubleQuote; -}); - -module.exports = String; - -},{"./literal":46}],74:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'switch'; - -/** - * Defines a switch statement - * @constructor Switch - * @extends {Statement} - * @property {Expression} test - * @property {Block} body - * @property {boolean} shortForm - */ -var Switch = Statement.extends(function Switch(test, body, shortForm, location) { - Statement.apply(this, [KIND, location]); - this.test = test; - this.body = body; - this.shortForm = shortForm; -}); - -module.exports = Switch; - -},{"./statement":70}],75:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Statement = require('./statement'); -var KIND = 'sys'; - -/** - * Defines system based call - * @constructor Sys - * @extends {Statement} - * @property {Node[]} arguments - */ -var Sys = Statement.extends(function Sys(kind, args, location) { - Statement.apply(this, [kind || KIND, location]); - this.arguments = args; -}); - -module.exports = Sys; - -},{"./statement":70}],76:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'throw'; - -/** - * Defines a throw statement - * @constructor Throw - * @extends {Statement} - * @property {Expression} what - */ -var Throw = Statement.extends(function Throw(what, location) { - Statement.apply(this, [KIND, location]); - this.what = what; -}); - -module.exports = Throw; - -},{"./statement":70}],77:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Declaration = require('./declaration'); -var KIND = 'trait'; - - -/** - * A trait definition - * @constructor Trait - * @extends {Declaration} - * @property {Identifier|null} extends - * @property {Identifier[]} implements - * @property {Declaration[]} body - */ -var Trait = Declaration.extends(function Trait(name, ext, impl, body, location) { - Declaration.apply(this, [KIND, name, location]); - this.extends = ext; - this.implements = impl; - this.body = body; -}); - -module.exports = Trait; - -},{"./declaration":20}],78:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Node = require('./node'); -var KIND = 'traitalias'; - -var IS_PUBLIC = 'public'; -var IS_PROTECTED = 'protected'; -var IS_PRIVATE = 'private'; - -/** - * Defines a trait alias - * @constructor TraitAlias - * @extends {Node} - * @property {Identifier|null} trait - * @property {string} method - * @property {string|null} as - * @property {string|null} visibility - */ -var TraitAlias = Node.extends(function TraitAlias(trait, method, as, flags, location) { - Node.apply(this, [KIND, location]); - this.trait = trait; - this.method = method; - this.as = as; - if (flags) { - if (flags[0] === 0) { - this.visibility = IS_PUBLIC; - } else if (flags[0] === 1) { - this.visibility = IS_PROTECTED; - } else { - this.visibility = IS_PRIVATE; - } - } else { - this.visibility = null; - } -}); - -module.exports = TraitAlias; - -},{"./node":53}],79:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Node = require('./node'); -var KIND = 'traitprecedence'; - -/** - * Defines a trait alias - * @constructor TraitPrecedence - * @extends {Node} - * @property {Identifier|null} trait - * @property {string} method - * @property {Identifier[]} instead - */ -var TraitPrecedence = Node.extends(function TraitPrecedence(trait, method, instead, location) { - Node.apply(this, [KIND, location]); - this.trait = trait; - this.method = method; - this.instead = instead; -}); - -module.exports = TraitPrecedence; - -},{"./node":53}],80:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Node = require('./node'); -var KIND = 'traituse'; - -/** - * Defines a trait usage - * @constructor TraitUse - * @extends {Node} - * @property {Identifier[]} traits - * @property {Node[]|null} adaptations - */ -var TraitUse = Node.extends(function TraitUse(traits, adaptations, location) { - Node.apply(this, [KIND, location]); - this.traits = traits; - this.adaptations = adaptations; -}); - -module.exports = TraitUse; - -},{"./node":53}],81:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'try'; - -/** - * Defines a try statement - * @constructor Try - * @extends {Statement} - * @property {Block} body - * @property {Catch[]} catches - * @property {Block} allways - */ -var Try = Statement.extends(function Try(body, catches, always, location) { - Statement.apply(this, [KIND, location]); - this.body = body; - this.catches = catches; - this.always = always; -}); - -module.exports = Try; - -},{"./statement":70}],82:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Operation = require('./operation'); -var KIND = 'unary'; - -/** - * Unary operations - * @constructor Unary - * @extends {Operation} - * @property {String} type - * @property {Expression} what - */ -var Unary = Operation.extends(function Unary(type, what, location) { - Operation.apply(this, [KIND, location]); - this.type = type; - this.what = what; -}); - -module.exports = Unary; - -},{"./operation":57}],83:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Sys = require('./sys'); -var KIND = 'unset'; - -/** - * Deletes references to a list of variables - * @constructor Unset - * @extends {Sys} - */ -var Unset = Sys.extends(function Unset(args, location) { - Sys.apply(this, [KIND, args, location]); -}); - -module.exports = Unset; - -},{"./sys":75}],84:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Statement = require('./statement'); -var KIND = 'usegroup'; - -/** - * Defines a use statement (with a list of use items) - * @constructor UseGroup - * @extends {Statement} - * @property {String|null} name - * @property {String|null} type - Possible value : function, const - * @property {UseItem[]} item - * @see {Namespace} - * @see http://php.net/manual/en/language.namespaces.importing.php - */ -var UseGroup = Statement.extends(function UseGroup(name, type, items, location) { - Statement.apply(this, [KIND, location]); - this.name = name; - this.type = type; - this.items = items; -}); - -module.exports = UseGroup; - -},{"./statement":70}],85:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Statement = require('./statement'); -var KIND = 'useitem'; - -/** - * Defines a use statement (from namespace) - * @constructor UseItem - * @extends {Statement} - * @property {String} name - * @property {String|null} type - Possible value : function, const - * @property {String|null} alias - * @see {Namespace} - * @see http://php.net/manual/en/language.namespaces.importing.php - */ -var UseItem = Statement.extends(function UseItem(name, alias, type, location) { - Statement.apply(this, [KIND, location]); - this.name = name; - this.alias = alias; - this.type = type; -}); - - -/** - * Importing a constant - * @constant {String} TYPE_CONST - */ -UseItem.TYPE_CONST = 'const'; -/** - * Importing a function - * @constant {String} TYPE_FUNC - */ -UseItem.TYPE_FUNCTION = 'function'; - - -module.exports = UseItem; - -},{"./statement":70}],86:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Expr = require('./expression'); -var KIND = 'variable'; - -/** - * Any expression node. Since the left-hand side of an assignment may - * be any expression in general, an expression can also be a pattern. - * @constructor Variable - * @extends {Expression} - * @example - * // PHP code : - * &$foo - * // AST output - * { - * "kind": "variable", - * "name": "foo", - * "byref": true, - * "curly": false - * } - * @property {String|Node} name The variable name (can be a complex expression when the name is resolved dynamically) - * @property {boolean} byref Indicate if the variable reference is used, ex `&$foo` - * @property {boolean} curly Indicate if the name is defined between curlies, ex `${foo}` - */ -var Variable = Expr.extends(function Variable(name, byref, curly, location) { - Expr.apply(this, [KIND, location]); - this.name = name; - this.byref = byref || false; - this.curly = curly || false; -}); - -module.exports = Variable; - -},{"./expression":31}],87:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -var Expr = require('./expression'); -var KIND = 'variadic'; - -/** - * Introduce a list of items into the arguments of the call - * @constructor Variadic - * @extends {Expression} - * @property {Array|Expression} what - * @see https://wiki.php.net/rfc/argument_unpacking - */ -var Variadic = Expr.extends(function Variadic(what, location) { - Expr.apply(this, [KIND, location]); - this.what = what; -}); - -module.exports = Variadic; - -},{"./expression":31}],88:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Statement = require('./statement'); -var KIND = 'while'; - -/** - * Defines a while statement - * @constructor While - * @extends {Statement} - * @property {Expression} test - * @property {Statement} body - * @property {boolean} shortForm - */ -var While = Statement.extends(function While(test, body, shortForm, location) { - Statement.apply(this, [KIND, location]); - this.test = test; - this.body = body; - this.shortForm = shortForm; -}); - -module.exports = While; - -},{"./statement":70}],89:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Expression = require('./expression'); -var KIND = 'yield'; - -/** - * Defines a yield generator statement - * @constructor Yield - * @extends {Expression} - * @property {Expression|Null} value - * @property {Expression|Null} key - * @see http://php.net/manual/en/language.generators.syntax.php - */ -var Yield = Expression.extends(function Yield(value, key, location) { - Expression.apply(this, [KIND, location]); - this.value = value; - this.key = key; -}); - -module.exports = Yield; - -},{"./expression":31}],90:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Expression = require('./expression'); -var KIND = 'yieldfrom'; - -/** - * Defines a yield from generator statement - * @constructor YieldFrom - * @extends {Expression} - * @property {Expression} value - * @see http://php.net/manual/en/language.generators.syntax.php - */ -var YieldFrom = Expression.extends(function YieldFrom(value, location) { - Expression.apply(this, [KIND, location]); - this.value = value; -}); - -module.exports = YieldFrom; - -},{"./expression":31}],91:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -/** - * This is the php lexer. It will tokenize the string for helping the - * parser to build the AST from its grammar. - * - * @public @constructor {Lexer} - * @property {Integer} EOF - * @property {Boolean} all_tokens defines if all tokens must be retrieved (used by token_get_all only) - * @property {Boolean} comment_tokens extracts comments tokens - * @property {Boolean} mode_eval enables the evald mode (ignore opening tags) - * @property {Boolean} asp_tags disables by default asp tags mode - * @property {Boolean} short_tags enables by default short tags mode - * @property {Object} keywords List of php keyword - * @property {Object} castKeywords List of php keywords for type casting - */ -var lexer = function(engine) { - this.engine = engine; - this.tok = this.engine.tokens.names; - this.EOF = 1; - this.debug = false; - this.all_tokens = true; - this.comment_tokens = false; - this.mode_eval = false; - this.asp_tags = false; - this.short_tags = true; - this.yyprevcol = 0; - this.keywords = { - "__class__": this.tok.T_CLASS_C, - "__trait__": this.tok.T_TRAIT_C, - "__function__": this.tok.T_FUNC_C, - "__method__": this.tok.T_METHOD_C, - "__line__": this.tok.T_LINE, - "__file__": this.tok.T_FILE, - "__dir__": this.tok.T_DIR, - "__namespace__": this.tok.T_NS_C, - 'exit': this.tok.T_EXIT, - 'die': this.tok.T_EXIT, - 'function': this.tok.T_FUNCTION, - "const": this.tok.T_CONST, - "return": this.tok.T_RETURN, - "try": this.tok.T_TRY, - "catch": this.tok.T_CATCH, - "finally": this.tok.T_FINALLY, - "throw": this.tok.T_THROW, - "if": this.tok.T_IF, - "elseif": this.tok.T_ELSEIF, - "endif": this.tok.T_ENDIF, - "else": this.tok.T_ELSE, - "while": this.tok.T_WHILE, - "endwhile": this.tok.T_ENDWHILE, - "do": this.tok.T_DO, - "for": this.tok.T_FOR, - "endfor": this.tok.T_ENDFOR, - "foreach": this.tok.T_FOREACH, - "endforeach": this.tok.T_ENDFOREACH, - "declare": this.tok.T_DECLARE, - "enddeclare": this.tok.T_ENDDECLARE, - "instanceof": this.tok.T_INSTANCEOF, - "as": this.tok.T_AS, - "switch": this.tok.T_SWITCH, - "endswitch": this.tok.T_ENDSWITCH, - "case": this.tok.T_CASE, - "default": this.tok.T_DEFAULT, - "break": this.tok.T_BREAK, - "continue": this.tok.T_CONTINUE, - "goto": this.tok.T_GOTO, - "echo": this.tok.T_ECHO, - "print": this.tok.T_PRINT, - "class": this.tok.T_CLASS, - "interface": this.tok.T_INTERFACE, - "trait": this.tok.T_TRAIT, - "extends": this.tok.T_EXTENDS, - "implements": this.tok.T_IMPLEMENTS, - "new": this.tok.T_NEW, - "clone": this.tok.T_CLONE, - "var": this.tok.T_VAR, - "eval": this.tok.T_EVAL, - "include": this.tok.T_INCLUDE, - "include_once": this.tok.T_INCLUDE_ONCE, - "require": this.tok.T_REQUIRE, - "require_once": this.tok.T_REQUIRE_ONCE, - "namespace": this.tok.T_NAMESPACE, - "use": this.tok.T_USE, - "insteadof": this.tok.T_INSTEADOF, - "global": this.tok.T_GLOBAL, - "isset": this.tok.T_ISSET, - "empty": this.tok.T_EMPTY, - "__halt_compiler": this.tok.T_HALT_COMPILER, - "static": this.tok.T_STATIC, - "abstract": this.tok.T_ABSTRACT, - "final": this.tok.T_FINAL, - "private": this.tok.T_PRIVATE, - "protected": this.tok.T_PROTECTED, - "public": this.tok.T_PUBLIC, - "unset": this.tok.T_UNSET, - "list": this.tok.T_LIST, - "array": this.tok.T_ARRAY, - "callable": this.tok.T_CALLABLE, - "or": this.tok.T_LOGICAL_OR, - "and": this.tok.T_LOGICAL_AND, - "xor": this.tok.T_LOGICAL_XOR - }; - this.castKeywords = { - 'int': this.tok.T_INT_CAST, - 'integer': this.tok.T_INT_CAST, - "real": this.tok.T_DOUBLE_CAST, - "double": this.tok.T_DOUBLE_CAST, - "float": this.tok.T_DOUBLE_CAST, - "string": this.tok.T_STRING_CAST, - "binary": this.tok.T_STRING_CAST, - "array": this.tok.T_ARRAY_CAST, - "object": this.tok.T_OBJECT_CAST, - "bool": this.tok.T_BOOL_CAST, - "boolean": this.tok.T_BOOL_CAST, - "unset": this.tok.T_UNSET_CAST - }; -}; - -/** - * Initialize the lexer with the specified input - */ -lexer.prototype.setInput = function(input) { - this._input = input; - this.size = input.length; - this.yylineno = 1; - this.offset = 0; - this.yyprevcol = 0; - this.yytext = ''; - this.yylloc = { - first_offset: 0, - first_line: 1, - first_column: 0, - prev_offset: 0, - prev_line: 1, - prev_column: 0, - last_line: 1, - last_column: 0 - }; - this.tokens = []; - this.conditionStack = []; - this.done = this.offset >= this.size; - if (!this.all_tokens && this.mode_eval) { - this.begin('ST_IN_SCRIPTING'); - } else { - this.begin('INITIAL'); - } - return this; -}; - - -/** - * consumes and returns one char from the input - */ -lexer.prototype.input = function(size) { - var ch = this._input[this.offset]; - if (!ch) return ''; - this.yytext += ch; - this.offset ++; - if ( ch === '\r' && this._input[this.offset] === '\n' ) { - this.yytext += '\n'; - this.offset++; - } - if (ch === '\n' || ch === '\r') { - this.yylloc.last_line = ++this.yylineno; - this.yyprevcol = this.yylloc.last_column; - this.yylloc.last_column = 0; - } else { - this.yylloc.last_column++; - } - return ch; -}; - -/** - * revert eating specified size - */ -lexer.prototype.unput = function(size) { - if (size === 1) { - // 1 char unput (most cases) - this.offset --; - if (this._input[this.offset] === '\n' && this._input[this.offset - 1] === '\r') { - this.offset --; - size ++; - } - if (this._input[this.offset] === '\r' || this._input[this.offset] === '\n') { - this.yylloc.last_line --; - this.yylineno --; - this.yylloc.last_column = this.yyprevcol; - } else { - this.yylloc.last_column --; - } - this.yytext = this.yytext.substring(0, this.yytext.length - size); - } else if (size > 0) { - this.offset -= size; - if (size < this.yytext.length) { - this.yytext = this.yytext.substring(0, this.yytext.length - size); - // re-calculate position - this.yylloc.last_line = this.yylloc.first_line; - this.yylloc.last_column = this.yyprevcol = this.yylloc.first_column; - for(var i = 0; i < this.yytext.length; i++) { - var c = this.yytext[i]; - if (c === '\r') { - c = this.yytext[++i]; - this.yyprevcol = this.yylloc.last_column; - this.yylloc.last_line ++; - this.yylloc.last_column = 0; - if (c !== '\n') { - if (c === '\r') { - this.yylloc.last_line ++; - } else { - this.yylloc.last_column ++; - } - } - } else if (c === '\n') { - this.yyprevcol = this.yylloc.last_column; - this.yylloc.last_line ++; - this.yylloc.last_column = 0; - } else { - this.yylloc.last_column ++; - } - } - this.yylineno = this.yylloc.last_line; - } else { - // reset full text - this.yytext = ""; - this.yylloc.last_line = this.yylineno = this.yylloc.first_line; - this.yylloc.last_column = this.yylloc.first_column; - } - } - - return this; -}; - -// check if the text matches -lexer.prototype.tryMatch = function(text) { - return text === this.ahead(text.length); -}; - -// check if the text matches -lexer.prototype.tryMatchCaseless = function(text) { - return text === this.ahead(text.length).toLowerCase(); -}; - -// look ahead -lexer.prototype.ahead = function(size) { - var text = this._input.substring(this.offset, this.offset + size); - if (text[text.length - 1] === '\r' && this._input[this.offset + size + 1] === '\n') { - text += '\n'; - } - return text; -}; - -// consume the specified size -lexer.prototype.consume = function(size) { - for(var i = 0; i < size; i++) { - var ch = this._input[this.offset]; - if (!ch) break; - this.yytext += ch; - this.offset ++; - if ( ch === '\r' && this._input[this.offset] === '\n' ) { - this.yytext += '\n'; - this.offset++; - i++; - } - if (ch === '\n' || ch === '\r') { - this.yylloc.last_line = ++this.yylineno; - this.yyprevcol = this.yylloc.last_column; - this.yylloc.last_column = 0; - } else { - this.yylloc.last_column++; - } - } - return this; -}; - -/** - * Gets the current state - */ -lexer.prototype.getState = function() { - return { - yytext: this.yytext, - offset: this.offset, - yylineno: this.yylineno, - yyprevcol: this.yyprevcol, - yylloc: { - first_offset: this.yylloc.first_offset, - first_line: this.yylloc.first_line, - first_column: this.yylloc.first_column, - last_line: this.yylloc.last_line, - last_column: this.yylloc.last_column - } - }; -}; - -/** - * Sets the current lexer state - */ -lexer.prototype.setState = function(state) { - this.yytext = state.yytext; - this.offset = state.offset; - this.yylineno = state.yylineno; - this.yyprevcol = state.yyprevcol; - this.yylloc = state.yylloc; - return this; -}; - -// prepend next token -lexer.prototype.appendToken = function(value, ahead) { - this.tokens.push([value, ahead]); - return this; -}; - -// return next match that has a token -lexer.prototype.lex = function() { - this.yylloc.prev_offset = this.offset; - this.yylloc.prev_line = this.yylloc.last_line; - this.yylloc.prev_column = this.yylloc.last_column; - var token = this.next() || this.lex(); - if (!this.all_tokens) { - while( - token === this.tok.T_WHITESPACE // ignore white space - || ( - !this.comment_tokens && ( - token === this.tok.T_COMMENT // ignore single lines comments - || token === this.tok.T_DOC_COMMENT // ignore doc comments - ) - ) - || ( - // ignore open tags - token === this.tok.T_OPEN_TAG - ) - ) { - token = this.next() || this.lex(); - } - if (!this.mode_eval && token == this.tok.T_OPEN_TAG_WITH_ECHO) { - // open tag with echo statement - return this.tok.T_ECHO; - } - } - if (!this.yylloc.prev_offset) { - this.yylloc.prev_offset = this.yylloc.first_offset; - this.yylloc.prev_line = this.yylloc.first_line; - this.yylloc.prev_column = this.yylloc.first_column; - } - /*else if (this.yylloc.prev_offset === this.offset && this.offset !== this.size) { - throw new Error('Infinite loop @ ' + this.offset + ' / ' + this.size); - }*/ - return token; -}; - -// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) -lexer.prototype.begin = function(condition) { - this.conditionStack.push(condition); - this.curCondition = condition; - this.stateCb = this['match' + condition]; - if (typeof this.stateCb !== 'function') { - throw new Error('Undefined condition state "'+condition+'"'); - } - return this; -}; - -// pop the previously active lexer condition state off the condition stack -lexer.prototype.popState = function() { - var n = this.conditionStack.length - 1; - var condition = (n > 0) ? this.conditionStack.pop() : this.conditionStack[0]; - this.curCondition = this.conditionStack[this.conditionStack.length - 1]; - this.stateCb = this['match' + this.curCondition]; - if (typeof this.stateCb !== 'function') { - throw new Error('Undefined condition state "'+this.curCondition+'"'); - } - return condition; -}; - -// return next match in input -lexer.prototype.next = function () { - var token; - if (!this._input) { - this.done = true; - } - this.yylloc.first_offset = this.offset; - this.yylloc.first_line = this.yylloc.last_line; - this.yylloc.first_column = this.yylloc.last_column; - this.yytext = ''; - if (this.done) { - this.yylloc.prev_offset = this.yylloc.first_offset; - this.yylloc.prev_line = this.yylloc.first_line; - this.yylloc.prev_column = this.yylloc.first_column; - return this.EOF; - } - if (this.tokens.length > 0) { - token = this.tokens.shift(); - if (typeof token[1] === 'object') { - this.setState(token[1]); - } else { - this.consume(token[1]); - } - token = token[0]; - } else { - token = this.stateCb.apply(this, []); - } - if (this.offset >= this.size && this.tokens.length === 0) { - this.done = true; - } - if (this.debug) { - var tName = token; - if (typeof tName === 'number') { - tName = this.engine.tokens.values[tName]; - } else { - tName = '"'+tName+'"'; - } - var e = new Error( - tName + - '\tfrom ' + this.yylloc.first_line + ',' + this.yylloc.first_column + - '\t - to ' + this.yylloc.last_line + ',' + this.yylloc.last_column + - '\t"'+this.yytext+'"' - ); - console.log(e.stack); - } - return token; -}; - - -// extends the lexer with states -[ - require('./lexer/comments.js'), - require('./lexer/initial.js'), - require('./lexer/numbers.js'), - require('./lexer/property.js'), - require('./lexer/scripting.js'), - require('./lexer/strings.js'), - require('./lexer/tokens.js'), - require('./lexer/utils.js') -].forEach(function (ext) { - for(var k in ext) { - lexer.prototype[k] = ext[k]; - } -}); - -module.exports = lexer; - -},{"./lexer/comments.js":92,"./lexer/initial.js":93,"./lexer/numbers.js":94,"./lexer/property.js":95,"./lexer/scripting.js":96,"./lexer/strings.js":97,"./lexer/tokens.js":98,"./lexer/utils.js":99}],92:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -"use strict"; - -module.exports = { - /** - * Reads a single line comment - * @see - */ - T_COMMENT: function() { - while(this.offset < this.size) { - var ch = this.input(); - if (ch === '\n' || ch === '\r') { - return this.tok.T_COMMENT; - } else if (ch === '?' && !this.aspTagMode && this._input[this.offset] === '>') { - this.unput(1); - return this.tok.T_COMMENT; - } else if (ch === '%' && this.aspTagMode && this._input[this.offset] === '>') { - this.unput(1); - return this.tok.T_COMMENT; - } - } - return this.tok.T_COMMENT; - }, - /** - * Behaviour : https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1927 - */ - T_DOC_COMMENT: function() { - var ch = this.input(); - var token = this.tok.T_COMMENT; - if (ch === '*') { // started with '/*' , check is next is '*' - ch = this.input(); - if (this.is_WHITESPACE()) { // check if next is WHITESPACE - token = this.tok.T_DOC_COMMENT; - } - if (ch === '/') { - return token; - } else { - this.unput(1); // reset - } - } - while(this.offset < this.size) { - ch = this.input(); - if (ch === '*' && this._input[this.offset] === '/') { - this.input(); - break; - } - } - return token; - } -}; - -},{}],93:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -module.exports = { - nextINITIAL: function() { - if ( - this.conditionStack.length > 1 - && this.conditionStack[this.conditionStack.length - 1] === 'INITIAL' - ) { - // Return to HEREDOC/ST_DOUBLE_QUOTES mode - this.popState(); - } else { - this.begin("ST_IN_SCRIPTING"); - } - return this; - }, - matchINITIAL: function() { - while(this.offset < this.size) { - var ch = this.input(); - if (ch == '<') { - ch = this.ahead(1); - if (ch == '?') { - if (this.tryMatch('?=')) { - this.unput(1).appendToken(this.tok.T_OPEN_TAG_WITH_ECHO, 3).nextINITIAL(); - break; - } else if (this.tryMatchCaseless('?php')) { - ch = this._input[this.offset + 4]; - if (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r') { - this.unput(1).appendToken(this.tok.T_OPEN_TAG, 6).nextINITIAL(); - break; - } - } - if (this.short_tags) { - this.unput(1).appendToken(this.tok.T_OPEN_TAG, 2).nextINITIAL(); - break; - } - } else if(this.asp_tags && ch == '%') { - if (this.tryMatch('%=')) { - this.aspTagMode = true; - this.unput(1).appendToken(this.tok.T_OPEN_TAG_WITH_ECHO, 3).nextINITIAL(); - break; - } else { - this.aspTagMode = true; - this.unput(1).appendToken(this.tok.T_OPEN_TAG, 2).nextINITIAL(); - break; - } - } - } - } - if (this.yytext.length > 0) { - return this.tok.T_INLINE_HTML; - } else { - return false; - } - } -}; - -},{}],94:[function(require,module,exports){ -(function (process){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -"use strict"; - -/* istanbul ignore else */ -if (process.arch == 'x64') { - var SIZEOF_LONG = 8; - var MAX_LENGTH_OF_LONG = 19; - var long_min_digits = "9223372036854775808"; -} else { - var SIZEOF_LONG = 4; - var MAX_LENGTH_OF_LONG = 10; - var long_min_digits = "2147483648"; -} - -module.exports = { - consume_NUM: function() { - var ch = this.yytext[0]; - var hasPoint = this.yytext[0] === '.'; - if (ch === '0') { - ch = this.input(); - // check if hexa - if (ch === 'x' || ch === 'X') { - this.input(); - if (this.is_HEX()) { - return this.consume_HNUM(); - } else { - this.unput(2); - } - } else if (ch === 'b' || ch === 'B') { - ch = this.input(); - if (ch === '0' || ch === '1') { - return this.consume_BNUM(); - } else { - this.unput(2); - } - } else if (!this.is_NUM()) { - this.unput(1); - } - } - - while(this.offset < this.size) { - ch = this.input(); - if (!this.is_NUM()) { - if (ch === '.' && !hasPoint) { - hasPoint = true; - } else if (ch === 'e' || ch === 'E') { - ch = this.input(); - if (ch === '+' || ch === '-') { - ch = this.input(); - if (this.is_NUM()) { - this.consume_LNUM(); - return this.tok.T_DNUMBER; - } else { - if (ch) this.unput(3); - break; - } - } else if (this.is_NUM()) { - this.consume_LNUM(); - return this.tok.T_DNUMBER; - } else { - if (ch) this.unput(2); - break; - } - } else { - this.unput(1); - break; - } - } - } - if (hasPoint) { - return this.tok.T_DNUMBER; - } else if (this.yytext.length < MAX_LENGTH_OF_LONG - 1) { - return this.tok.T_LNUMBER; - } else { - if ( - this.yytext.length < MAX_LENGTH_OF_LONG || ( - this.yytext.length == MAX_LENGTH_OF_LONG - && this.yytext < long_min_digits - ) - ) { - return this.tok.T_LNUMBER; - } - return this.tok.T_DNUMBER; - } - }, - // read hexa - consume_HNUM: function() { - while(this.offset < this.size) { - this.input(); - if (!this.is_HEX()) { - this.unput(1); - break; - } - } - return this.tok.T_LNUMBER; - }, - // read a generic number - consume_LNUM: function() { - while(this.offset < this.size) { - this.input(); - if (!this.is_NUM()) { - this.unput(1); - break; - } - } - return this.tok.T_LNUMBER; - }, - // read binary - consume_BNUM: function() { - var ch; - while(this.offset < this.size) { - ch = this.input(); - if (ch !== '0' && ch !== '1') { - if (ch) this.unput(1); - break; - } - } - return this.tok.T_LNUMBER; - } -}; - -}).call(this,require('_process')) -},{"_process":1}],95:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -module.exports = { - matchST_LOOKING_FOR_PROPERTY: function() { - var ch = this.input(); - if (ch === '-') { - ch = this.input(); - if (ch === '>') { - // https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1296 - return this.tok.T_OBJECT_OPERATOR; - } - if (ch) this.unput(1); - } else if (this.is_LABEL_START()) { - // https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1300 - this.consume_LABEL(); - this.popState(); - return this.tok.T_STRING; - } - // https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1306 - this.popState(); - if (ch) this.unput(1); - return false; - }, - matchST_LOOKING_FOR_VARNAME: function() { - var ch = this.input(); - if (this.is_LABEL_START()) { - this.consume_LABEL(); - ch = this.input(); - this.popState(); - if (ch === '[' || ch === '}') { - this.begin('ST_IN_SCRIPTING'); - this.unput(1); - return this.tok.T_STRING_VARNAME; - } else { - this.unput(this.yytext.length); - return false; - } - } else { - if (ch) this.unput(1); - this.popState(); - this.begin('ST_IN_SCRIPTING'); - // console.log(this.yylineno, 'ST_LOOKING_FOR_VARNAME', this._input[this.offset - 1], this.conditionStack); - return false; - } - }, - matchST_VAR_OFFSET: function() { - var ch = this.input(); - if (this.is_NUM()) { - this.consume_NUM(); - return this.tok.T_NUM_STRING; - } else if (ch === ']') { - this.popState(); - return ']'; - } else if (ch === '$') { - this.input(); - if (this.is_LABEL_START()) { - this.consume_LABEL(); - return this.tok.T_VARIABLE; - } else { - throw new Error('Unexpected terminal'); - } - } else if (this.is_LABEL_START()) { - this.consume_LABEL(); - return this.tok.T_STRING; - } else if (this.is_WHITESPACE() || ch === '\\' || ch === '\'' || ch === '#') { - return this.tok.T_ENCAPSED_AND_WHITESPACE; - } else if (ch === '[' || ch === '{' || ch === '}' || ch === '"' || ch === '`' || this.is_TOKEN()) { - return ch; - } else { - throw new Error('Unexpected terminal'); - } - } -}; - -},{}],96:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -module.exports = { - matchST_IN_SCRIPTING: function() { - var ch = this.input(); - switch(ch) { - case ' ': - case '\t': - case '\n': - case '\r': - case '\r\n': - return this.T_WHITESPACE(); - case '#': - return this.T_COMMENT(); - case '/': - if (this._input[this.offset] === '/') { - return this.T_COMMENT(); - } else if (this._input[this.offset] === '*') { - this.input(); - return this.T_DOC_COMMENT(); - } - return this.consume_TOKEN(); - case '\'': - return this.T_CONSTANT_ENCAPSED_STRING(); - case '"': - return this.ST_DOUBLE_QUOTES(); - case '`': - this.begin('ST_BACKQUOTE'); - return '`'; - case '?': - if (!this.aspTagMode && this.tryMatch('>')) { - this.input(); - var nextCH = this._input[this.offset]; - if (nextCH === '\n' || nextCH === '\r') this.input(); - if (this.conditionStack.length > 1) { - this.begin('INITIAL'); - } - return this.tok.T_CLOSE_TAG; - } - return this.consume_TOKEN(); - case '%': - if (this.aspTagMode && this._input[this.offset] === '>') { - this.input(); // consume the '>' - ch = this._input[this.offset]; // read next - if (ch === '\n' || ch === '\r') { - this.input(); // consume the newline - } - this.aspTagMode = false; - if (this.conditionStack.length > 1) { - this.begin('INITIAL'); - } - return this.tok.T_CLOSE_TAG; - } - return this.consume_TOKEN(); - case '{': - this.begin('ST_IN_SCRIPTING'); - return '{'; - case '}': - if (this.conditionStack.length > 2) { - // Return to HEREDOC/ST_DOUBLE_QUOTES mode - this.popState(); - } - return '}'; - default: - if (ch === '.') { - ch = this.input(); - if (this.is_NUM()) { - return this.consume_NUM(); - } else { - if (ch) this.unput(1); - } - } - if (this.is_NUM()) { - return this.consume_NUM(); - } else if (this.is_LABEL_START()) { - return this.consume_LABEL().T_STRING(); - } else if(this.is_TOKEN()) { - return this.consume_TOKEN(); - } - } - throw new Error( - 'Bad terminal sequence "' + ch + '" at line ' + this.yylineno + ' (offset ' + this.offset + ')' - ); - }, - - T_WHITESPACE: function() { - while(this.offset < this.size) { - var ch = this.input(); - if (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r') { - continue; - } - this.unput(1); - break; - } - return this.tok.T_WHITESPACE; - } -}; - -},{}],97:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -module.exports = { - T_CONSTANT_ENCAPSED_STRING: function() { - var ch; - while(this.offset < this.size) { - ch = this.input(); - if (ch == '\\') { - this.input(); - } else if (ch == '\'') { - break; - } - } - return this.tok.T_CONSTANT_ENCAPSED_STRING; - }, - // check if matching a HEREDOC state - is_HEREDOC: function() { - var revert = this.offset; - if ( - this._input[this.offset - 1] === '<' - && this._input[this.offset] === '<' - && this._input[this.offset + 1] === '<' - ) { - this.offset += 3; - - // optional tabs / spaces - if (this.is_TABSPACE()) { - while(this.offset < this.size) { - this.offset ++; - if (!this.is_TABSPACE()) { - break; - } - } - } - - // optional quotes - var tChar = this._input[this.offset - 1]; - if (tChar === '\'' || tChar === '"') { - this.offset ++; - } else { - tChar = null; - } - - // required label - if (this.is_LABEL_START()) { - var yyoffset = this.offset - 1; - while(this.offset < this.size) { - this.offset++; - if (!this.is_LABEL()) { - break; - } - } - var yylabel = this._input.substring(yyoffset, this.offset - 1); - if (!tChar || tChar === this._input[this.offset - 1]) { // required ending quote - if (tChar) this.offset ++; - // require newline - if (this._input[this.offset - 1] === '\r' || this._input[this.offset - 1] === '\n') { - // go go go - this.heredoc_label = yylabel; - yyoffset = this.offset - revert; - this.offset = revert; - this.consume(yyoffset); - if (tChar === '\'') { - this.begin('ST_NOWDOC'); - } else { - this.begin('ST_HEREDOC'); - } - return this.tok.T_START_HEREDOC; - } - } - } - } - this.offset = revert; - return false; - }, - ST_DOUBLE_QUOTES: function() { - var ch; - while(this.offset < this.size) { - ch = this.input(); - if (ch == '\\') { - this.input(); - } else if (ch == '"') { - break; - } else if (ch == '$') { - ch = this.input(); - if ( ch == '{' || this.is_LABEL_START()) { - this.unput(2); - break; - } - this.unput(1); - } else if (ch == '{') { - ch = this.input(); - if (ch == '$') { - this.unput(2); - break; - } - this.unput(1); - } - } - if (ch == '"') { - return this.tok.T_CONSTANT_ENCAPSED_STRING; - } else { - var prefix = 1; - if (this.yytext[0] === 'b' || this.yytext[0] === 'B') { - prefix = 2; - } - if (this.yytext.length > 2) { - this.appendToken( - this.tok.T_ENCAPSED_AND_WHITESPACE, - this.yytext.length - prefix - ); - } - this.unput(this.yytext.length - prefix); - this.begin("ST_DOUBLE_QUOTES"); - return this.yytext; - } - }, - - // check if its a DOC end sequence - isDOC_MATCH: function() { - // @fixme : check if out of text limits - if (this._input.substring(this.offset - 1, this.offset - 1 + this.heredoc_label.length) === this.heredoc_label) { - var ch = this._input[this.offset - 1 + this.heredoc_label.length]; - if (ch === '\n' || ch === '\r' || ch === ';') { - return true; - } - } - return false; - }, - - matchST_NOWDOC: function() { - /** edge case : empty now doc **/ - if (this.isDOC_MATCH()) { - // @fixme : never reached (may be caused by quotes) - this.consume(this.heredoc_label.length); - this.popState(); - return this.tok.T_END_HEREDOC; - } - /** SCANNING CONTENTS **/ - var ch = this._input[this.offset - 1]; - while(this.offset < this.size) { - if (ch === '\n' || ch === '\r') { - ch = this.input(); - if (this.isDOC_MATCH()) { - this.unput(1).popState(); - this.appendToken( - this.tok.T_END_HEREDOC, this.heredoc_label.length - ); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - } - } else { - ch = this.input(); - } - } - // too bad ! reached end of document (will get a parse error) - return this.tok.T_ENCAPSED_AND_WHITESPACE; - }, - - matchST_HEREDOC: function() { - /** edge case : empty here doc **/ - var ch = this.input(); - if (this.isDOC_MATCH()) { - this.consume(this.heredoc_label.length - 1); - this.popState(); - return this.tok.T_END_HEREDOC; - } - /** SCANNING CONTENTS **/ - while(this.offset < this.size) { - - if (ch === '\\') { - ch = this.input(); // ignore next - if (ch !== '\n' && ch !== '\r') { - ch = this.input(); - } - } - - if (ch === '\n' || ch === '\r') { - ch = this.input(); - if (this.isDOC_MATCH()) { - this.unput(1).popState(); - this.appendToken( - this.tok.T_END_HEREDOC, this.heredoc_label.length - ); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - } - } else if (ch === '$') { - ch = this.input(); - if (ch === '{') { - // start of ${ - this.begin('ST_LOOKING_FOR_VARNAME'); - if (this.yytext.length > 2) { - this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2); - this.unput(2); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - }else { - return this.tok.T_DOLLAR_OPEN_CURLY_BRACES; - } - } else if (this.is_LABEL_START()) { - // start of $var... - var yyoffset = this.offset; - var next = this.consume_VARIABLE(); - if (this.yytext.length > this.offset - yyoffset + 2) { - this.appendToken(next, this.offset - yyoffset + 2); - this.unput(this.offset - yyoffset + 2); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - } else { - return next; - } - //console.log(this.yytext); - } - } else if (ch === '{') { - ch = this.input(); - if (ch === '$') { - // start of {$... - this.begin('ST_IN_SCRIPTING'); - if (this.yytext.length > 2) { - this.appendToken(this.tok.T_CURLY_OPEN, 1); - this.unput(2); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - } else { - this.unput(1); - return this.tok.T_CURLY_OPEN; - } - } - } else { - ch = this.input(); - } - } - - // too bad ! reached end of document (will get a parse error) - return this.tok.T_ENCAPSED_AND_WHITESPACE; - }, - - consume_VARIABLE: function() { - this.consume_LABEL(); - ch = this.input(); - if (ch == '[') { - this.unput(1); - this.begin('ST_VAR_OFFSET'); - return this.tok.T_VARIABLE; - } else if (ch === '-') { - if (this.input() === '>') { - this.input(); - if (this.is_LABEL_START()) { - this.begin('ST_LOOKING_FOR_PROPERTY'); - } - this.unput(3); - return this.tok.T_VARIABLE; - } else { - this.unput(2); - } - } else { - this.unput(1); - } - return this.tok.T_VARIABLE; - }, - // HANDLES BACKQUOTES - matchST_BACKQUOTE: function() { - - var ch = this.input(); - if (ch === '$') { - ch = this.input(); - if (ch === '{') { - this.begin('ST_LOOKING_FOR_VARNAME'); - return this.tok.T_DOLLAR_OPEN_CURLY_BRACES; - } else if (this.is_LABEL_START()) { - var tok = this.consume_VARIABLE(); - return tok; - } - } else if (ch === '{') { - if (this._input[this.offset] === '$') { - this.begin('ST_IN_SCRIPTING'); - return this.tok.T_CURLY_OPEN; - } - } else if (ch === '`') { - this.popState(); - return '`'; - } - - // any char - while(this.offset < this.size) { - if (ch === '\\') { - this.input(); - } else if (ch === '`') { - this.unput(1); - this.popState(); - this.appendToken('`', 1); - break; - } else if (ch === '$') { - ch = this.input(); - if (ch === '{') { - this.begin('ST_LOOKING_FOR_VARNAME'); - if (this.yytext.length > 2) { - this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2); - this.unput(2); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - }else { - return this.tok.T_DOLLAR_OPEN_CURLY_BRACES; - } - } else if (this.is_LABEL_START()) { - // start of $var... - var yyoffset = this.offset; - var next = this.consume_VARIABLE(); - if (this.yytext.length > this.offset - yyoffset + 2) { - this.appendToken(next, this.offset - yyoffset + 2); - this.unput(this.offset - yyoffset + 2); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - } else { - return next; - } - } - this.unput(1); - } else if (ch === '{') { - ch = this.input(); - if (ch === '$') { - // start of {$... - this.begin('ST_IN_SCRIPTING'); - if (this.yytext.length > 2) { - this.appendToken(this.tok.T_CURLY_OPEN, 1); - this.unput(2); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - } else { - this.unput(1); - return this.tok.T_CURLY_OPEN; - } - } - this.unput(1); - } - ch = this.input(); - } - return this.tok.T_ENCAPSED_AND_WHITESPACE; - - }, - - matchST_DOUBLE_QUOTES: function() { - - var ch = this.input(); - if (ch === '$') { - ch = this.input(); - if (ch === '{') { - this.begin('ST_LOOKING_FOR_VARNAME'); - return this.tok.T_DOLLAR_OPEN_CURLY_BRACES; - } else if (this.is_LABEL_START()) { - var tok = this.consume_VARIABLE(); - return tok; - } - } else if (ch === '{') { - if (this._input[this.offset] === '$') { - this.begin('ST_IN_SCRIPTING'); - return this.tok.T_CURLY_OPEN; - } - } else if (ch === '"') { - this.popState(); - return '"'; - } - - // any char - while(this.offset < this.size) { - if (ch === '\\') { - this.input(); - } else if (ch === '"') { - this.unput(1); - this.popState(); - this.appendToken('"', 1); - break; - } else if (ch === '$') { - ch = this.input(); - if (ch === '{') { - this.begin('ST_LOOKING_FOR_VARNAME'); - if (this.yytext.length > 2) { - this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2); - this.unput(2); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - }else { - return this.tok.T_DOLLAR_OPEN_CURLY_BRACES; - } - } else if (this.is_LABEL_START()) { - // start of $var... - var yyoffset = this.offset; - var next = this.consume_VARIABLE(); - if (this.yytext.length > this.offset - yyoffset + 2) { - this.appendToken(next, this.offset - yyoffset + 2); - this.unput(this.offset - yyoffset + 2); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - } else { - return next; - } - } - this.unput(1); - } else if (ch === '{') { - ch = this.input(); - if (ch === '$') { - // start of {$... - this.begin('ST_IN_SCRIPTING'); - if (this.yytext.length > 2) { - this.appendToken(this.tok.T_CURLY_OPEN, 1); - this.unput(2); - return this.tok.T_ENCAPSED_AND_WHITESPACE; - } else { - // @fixme : yytext = '"{$' (this.yytext.length > 3) - this.unput(1); - return this.tok.T_CURLY_OPEN; - } - } - if (ch) this.unput(1); - } - ch = this.input(); - } - return this.tok.T_ENCAPSED_AND_WHITESPACE; - } -}; - -},{}],98:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -module.exports = { - T_STRING: function() { - var token = this.yytext.toLowerCase(); - var id = this.keywords[token]; - if (!id) { - if (token === 'yield') { - if (this.tryMatch(' from')) { - this.consume(5); - id = this.tok.T_YIELD_FROM; - } else { - id = this.tok.T_YIELD; - } - } else { - id = this.tok.T_STRING; - if (token === 'b' || token === 'B') { - var ch = this.input(1); - if (ch === '"') { - return this.ST_DOUBLE_QUOTES(); - } else if (ch === '\'') { - return this.T_CONSTANT_ENCAPSED_STRING(); - } else if (ch) { - this.unput(1); - } - } - } - } - return id; - }, - // reads a custom token - consume_TOKEN: function() { - var ch = this._input[this.offset - 1]; - var fn = this.tokenTerminals[ch]; - if (fn) { - return fn.apply(this, []); - } else { - return this.yytext; - } - }, - // list of special char tokens - tokenTerminals: { - '$': function() { - this.offset++; - if (this.is_LABEL_START()) { - this.offset--; - this.consume_LABEL(); - return this.tok.T_VARIABLE; - } else { - this.offset--; - return '$'; - } - }, - '-': function() { - var nchar = this._input[this.offset]; - if (nchar === '>') { - this.begin('ST_LOOKING_FOR_PROPERTY').input(); - return this.tok.T_OBJECT_OPERATOR; - } else if (nchar === '-') { - this.input(); - return this.tok.T_DEC; - } else if (nchar === '=') { - this.input(); - return this.tok.T_MINUS_EQUAL; - } - return '-'; - }, - '\\': function() { - return this.tok.T_NS_SEPARATOR; - }, - '/': function() { - if (this._input[this.offset] === '=') { - this.input(); - return this.tok.T_DIV_EQUAL; - } - return '/'; - }, - ':': function() { - if (this._input[this.offset] === ':') { - this.input(); - return this.tok.T_DOUBLE_COLON; - } else { - return ':'; - } - }, - '(': function() { - var initial = this.offset; - this.input(); - if (this.is_TABSPACE()) { - this.consume_TABSPACE().input(); - } - if (this.is_LABEL_START()) { - var yylen = this.yytext.length; - this.consume_LABEL(); - var castToken = this.yytext.substring(yylen - 1).toLowerCase(); - var castId = this.castKeywords[castToken]; - if (castId) { - this.input(); - if (this.is_TABSPACE()) { - this.consume_TABSPACE().input(); - } - if (this._input[this.offset - 1] === ')') { - return castId; - } - } - } - // revert the check - this.unput(this.offset - initial); - return '('; - }, - '=': function() { - var nchar = this._input[this.offset]; - if (nchar === '>') { - this.input(); - return this.tok.T_DOUBLE_ARROW; - } else if (nchar === '=') { - if (this._input[this.offset + 1] === '=') { - this.consume(2); - return this.tok.T_IS_IDENTICAL; - } else { - this.input(); - return this.tok.T_IS_EQUAL; - } - } - return '='; - }, - '+': function() { - var nchar = this._input[this.offset]; - if (nchar === '+') { - this.input(); - return this.tok.T_INC; - } else if (nchar === '=') { - this.input(); - return this.tok.T_PLUS_EQUAL; - } - return '+'; - }, - '!': function() { - if (this._input[this.offset] === '=') { - if (this._input[this.offset + 1] === '=') { - this.consume(2); - return this.tok.T_IS_NOT_IDENTICAL; - } else { - this.input(); - return this.tok.T_IS_NOT_EQUAL; - } - } - return '!'; - }, - '?': function() { - if (this._input[this.offset] === '?') { - this.input(); - return this.tok.T_COALESCE; - } - return '?'; - }, - '<': function() { - var nchar = this._input[this.offset]; - if (nchar === '<') { - nchar = this._input[this.offset + 1]; - if (nchar === '=') { - this.consume(2); - return this.tok.T_SL_EQUAL; - } else if (nchar === '<') { - if (this.is_HEREDOC()) { - return this.tok.T_START_HEREDOC; - } - } - this.input(); - return this.tok.T_SL; - } else if (nchar === '=') { - this.input(); - if (this._input[this.offset] === '>') { - this.input(); - return this.tok.T_SPACESHIP; - } else { - return this.tok.T_IS_SMALLER_OR_EQUAL; - } - } else if (nchar === '>') { - this.input(); - return this.tok.T_IS_NOT_EQUAL; - } - return '<'; - }, - '>': function() { - var nchar = this._input[this.offset]; - if (nchar === '=') { - this.input(); - return this.tok.T_IS_GREATER_OR_EQUAL; - } else if (nchar === '>') { - nchar = this._input[this.offset + 1]; - if (nchar === '=') { - this.consume(2); - return this.tok.T_SR_EQUAL; - } else { - this.input(); - return this.tok.T_SR; - } - } - return '>'; - }, - '*': function() { - var nchar = this._input[this.offset]; - if (nchar === '=') { - this.input(); - return this.tok.T_MUL_EQUAL; - } else if(nchar === '*') { - this.input(); - if (this._input[this.offset] === '=') { - this.input(); - return this.tok.T_POW_EQUAL; - } else { - return this.tok.T_POW; - } - } - return '*'; - }, - '.': function() { - var nchar = this._input[this.offset]; - if (nchar === '=') { - this.input(); - return this.tok.T_CONCAT_EQUAL; - } else if (nchar === '.' && this._input[this.offset + 1] === '.') { - this.consume(2); - return this.tok.T_ELLIPSIS; - } - return '.'; - }, - '%': function() { - if (this._input[this.offset] === '=') { - this.input(); - return this.tok.T_MOD_EQUAL; - } - return '%'; - }, - '&': function() { - var nchar = this._input[this.offset]; - if (nchar === '=') { - this.input(); - return this.tok.T_AND_EQUAL; - } else if (nchar === '&') { - this.input(); - return this.tok.T_BOOLEAN_AND; - } - return '&'; - }, - '|': function() { - var nchar = this._input[this.offset]; - if (nchar === '=') { - this.input(); - return this.tok.T_OR_EQUAL; - } else if (nchar === '|') { - this.input(); - return this.tok.T_BOOLEAN_OR; - } - return '|'; - }, - '^': function() { - if (this._input[this.offset] === '=') { - this.input(); - return this.tok.T_XOR_EQUAL; - } - return '^'; - } - } -}; - -},{}],99:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - var tokens = ';:,.\\[]()|^&+-/*=%!~$<>?@'; - -module.exports = { - - // check if the char can be a numeric - is_NUM: function() { - var ch = this._input.charCodeAt(this.offset - 1); - return ch > 47 && ch < 58; - }, - - // check if current char can be a label - is_LABEL: function() { - var ch = this._input.charCodeAt(this.offset - 1); - return (ch > 96 && ch < 123) - || (ch > 64 && ch < 91) - || ch === 95 - || (ch > 47 && ch < 58) - || ch > 126 - ; - }, - - // check if current char can be a label - is_LABEL_START: function() { - var ch = this._input.charCodeAt(this.offset - 1); - return (ch > 96 && ch < 123) - || (ch > 64 && ch < 91) - || ch === 95 - || (ch > 126) - ; - }, - - - // reads each char of the label - consume_LABEL: function() { - while(this.offset < this.size) { - this.input(); - if (!this.is_LABEL()) { - this.unput(1); - break; - } - } - return this; - }, - - // check if current char is a token char - is_TOKEN: function() { - var ch = this._input[this.offset - 1]; - return tokens.indexOf(ch) !== -1; - }, - // check if current char is a whitespace - is_WHITESPACE: function() { - var ch = this._input[this.offset - 1]; - return ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r'; - }, - // check if current char is a whitespace (without newlines) - is_TABSPACE: function() { - var ch = this._input[this.offset - 1]; - return ch === ' ' || ch === '\t'; - }, - // consume all whitespaces (excluding newlines) - consume_TABSPACE: function() { - while(this.offset < this.size) { - this.input(); - if (!this.is_TABSPACE()) { - this.unput(1); - break; - } - } - return this; - }, - // check if current char can be a hexadecimal number - is_HEX: function() { - var ch = this._input.charCodeAt(this.offset - 1); - return (ch > 47 && ch < 58) || (ch > 64 && ch < 71) || (ch > 96 && ch < 103); - } -}; - -},{}],100:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -/** - * @private check if argument is a number - */ -function isNumber(n) { - return n != '.' && n != ',' && !isNaN(parseFloat(n)) && isFinite(n); -} - - -/** - * The PHP Parser class that build the AST tree from the lexer - * @constructor {Parser} - * @property {Lexer} lexer - current lexer instance - * @property {AST} ast - the AST factory instance - * @property {Integer|String} token - current token - * @property {Boolean} extractDoc - should extract documentation as AST node - * @property {Boolean} suppressErrors - should ignore parsing errors and continue - * @property {Boolean} debug - should output debug informations - */ -var parser = function(lexer, ast) { - this.lexer = lexer; - this.ast = ast; - this.tok = lexer.tok; - this.EOF = lexer.EOF; - this.token = null; - this.prev = null; - this.debug = false; - this.extractDoc = false; - this.suppressErrors = false; - this.entries = { - 'VARIABLE': [ - this.tok.T_VARIABLE, - '$', '&', - this.tok.T_NS_SEPARATOR, - this.tok.T_STRING, - this.tok.T_NAMESPACE, - this.tok.T_STATIC - ], - 'SCALAR': [ - this.tok.T_CONSTANT_ENCAPSED_STRING, - this.tok.T_START_HEREDOC, - this.tok.T_LNUMBER, - this.tok.T_DNUMBER, - this.tok.T_ARRAY,'[', - this.tok.T_CLASS_C, - this.tok.T_TRAIT_C, - this.tok.T_FUNC_C, - this.tok.T_METHOD_C, - this.tok.T_LINE, - this.tok.T_FILE, - this.tok.T_DIR, - this.tok.T_NS_C, - '"', - 'b"', - 'B"', - '-', - this.tok.T_NS_SEPARATOR - ], - 'T_MAGIC_CONST': [ - this.tok.T_CLASS_C, - this.tok.T_TRAIT_C, - this.tok.T_FUNC_C, - this.tok.T_METHOD_C, - this.tok.T_LINE, - this.tok.T_FILE, - this.tok.T_DIR, - this.tok.T_NS_C - ], - 'T_MEMBER_FLAGS': [ - this.tok.T_PUBLIC, - this.tok.T_PRIVATE, - this.tok.T_PROTECTED, - this.tok.T_STATIC, - this.tok.T_ABSTRACT, - this.tok.T_FINAL - ], - 'EOS': [ - ';', - this.tok.T_CLOSE_TAG, - this.EOF, - this.tok.T_INLINE_HTML - ], - 'EXPR': [ - '@','-','+','!','~','(','`', - this.tok.T_LIST, - this.tok.T_CLONE, - this.tok.T_INC, - this.tok.T_DEC, - this.tok.T_NEW, - this.tok.T_ISSET, - this.tok.T_EMPTY, - this.tok.T_INCLUDE, - this.tok.T_INCLUDE_ONCE, - this.tok.T_REQUIRE, - this.tok.T_REQUIRE_ONCE, - this.tok.T_EVAL, - this.tok.T_INT_CAST, - this.tok.T_DOUBLE_CAST, - this.tok.T_STRING_CAST, - this.tok.T_ARRAY_CAST, - this.tok.T_OBJECT_CAST, - this.tok.T_BOOL_CAST, - this.tok.T_UNSET_CAST, - this.tok.T_EXIT, - this.tok.T_PRINT, - this.tok.T_YIELD, - this.tok.T_STATIC, - this.tok.T_FUNCTION, - // using VARIABLES : - this.tok.T_VARIABLE, - '$', - this.tok.T_NS_SEPARATOR, - this.tok.T_STRING, - // using SCALAR : - this.tok.T_STRING, // @see variable.js line 45 > conflict with variable = shift/reduce :) - this.tok.T_CONSTANT_ENCAPSED_STRING, - this.tok.T_START_HEREDOC, - this.tok.T_LNUMBER, - this.tok.T_DNUMBER, - this.tok.T_ARRAY,'[', - this.tok.T_CLASS_C, - this.tok.T_TRAIT_C, - this.tok.T_FUNC_C, - this.tok.T_METHOD_C, - this.tok.T_LINE, - this.tok.T_FILE, - this.tok.T_DIR, - this.tok.T_NS_C - ] - }; -}; - -/** - * helper : gets a token name - */ -parser.prototype.getTokenName = function(token) { - if (!isNumber(token)) { - return "'" + token + "'"; - } else { - if (token == this.EOF) return 'the end of file (EOF)'; - return this.lexer.engine.tokens.values[token]; - } -}; - -/** - * main entry point : converts a source code to AST - */ -parser.prototype.parse = function(code, filename) { - this._errors = []; - this.filename = filename || 'eval'; - this.currentNamespace = ['']; - this.lexer.setInput(code); - this.lexer.comment_tokens = this.extractDoc; - this.length = this.lexer._input.length; - this.innerList = false; - var program = this.ast.prepare('program', this); - var childs = []; - this.nextWithComments(); - while(this.token != this.EOF) { - var node = this.read_start(); - if (node !== null && node !== undefined) { - if (Array.isArray(node)) { - childs = childs.concat(node); - } else { - childs.push(node); - } - } - } - return program(childs, this._errors); -}; - -/** - * Raise an error - */ -parser.prototype.raiseError = function(message, msgExpect, expect, token) { - message += ' on line ' + this.lexer.yylloc.first_line; - if (!this.suppressErrors) { - var err = new SyntaxError( - message, this.filename, this.lexer.yylloc.first_line - ); - err.lineNumber = this.lexer.yylloc.first_line; - err.fileName = this.filename; - err.columnNumber = this.lexer.yylloc.first_column - throw err; - } - // Error node : - var node = this.ast.prepare('error', this)( - message, token, this.lexer.yylloc.first_line, expect - ); - this._errors.push(node); - return node; -}; - -/** - * handling errors - */ -parser.prototype.error = function(expect) { - var msg = 'Parse Error : syntax error'; - token = this.getTokenName(this.token); - if (this.token !== this.EOF) { - if (isNumber(this.token)) { - var symbol = this.text(); - if (symbol.length > 10) { - symbol = symbol.substring(0, 7) + '...'; - } - token = '\''+symbol+'\' ('+token+')'; - } - msg += ', unexpected ' + token; - } - var msgExpect = ''; - if (expect && !Array.isArray(expect)) { - if (isNumber(expect) || expect.length === 1) { - msgExpect = ', expecting ' + this.getTokenName(expect); - } - msg += msgExpect; - } - this.token !== this.EOF - return this.raiseError( - msg, - msgExpect, - expect, - token - ); -}; - -/** - * Creates a new AST node - */ -parser.prototype.node = function(name) { - return this.ast.prepare(name, this); -}; - -/** - * expects an end of statement or end of file - * @return {boolean} - */ -parser.prototype.expectEndOfStatement = function() { - if (this.token === ';') { - this.nextWithComments(); - if (this.token === this.tok.T_CLOSE_TAG) { - // strip close tag (statement already closed with ';') - this.nextWithComments(); - } - } else if (this.token === this.tok.T_CLOSE_TAG) { - this.nextWithComments(); - } else if (this.token !== this.tok.T_INLINE_HTML && this.token !== this.EOF) { - this.error(';'); - return false; - } - return true; -}; - -/** outputs some debug information on current token **/ -var ignoreStack = ['parser.next', 'parser.ignoreComments', 'parser.nextWithComments']; -parser.prototype.showlog = function() { - var stack = (new Error()).stack.split('\n'); - var line; - for (var offset = 2; offset < stack.length; offset ++) { - line = stack[offset].trim(); - var found = false; - for(var i = 0; i < ignoreStack.length; i++) { - if (line.substring(3, 3 + ignoreStack[i].length) === ignoreStack[i]) { - found = true; - break; - } - } - if (!found) { - break; - } - } - - console.log( - 'Line ' - + this.lexer.yylloc.first_line - + ' : ' - + this.getTokenName(this.token) - + ">" + this.lexer.yytext + "<" - + ' @-->' + line - ); - return this; -}; - -/** - * Force the parser to check the current token. - * - * If the current token does not match to expected token, - * the an error will be raised. - * - * If the suppressError mode is activated, then the error will - * be added to the program error stack and this function will return `false`. - * - * @param {String|Number} token - * @return {boolean} - * @throws Error - */ -parser.prototype.expect = function(token) { - if (Array.isArray(token)) { - if (token.indexOf(this.token) === -1) { - this.error(token); - return false; - } - } else if (this.token != token) { - this.error(token); - return false; - } - return true; -}; - -/** - * Returns the current token contents - * @return {String} - */ -parser.prototype.text = function() { - return this.lexer.yytext; -}; - -/** consume the next token **/ -parser.prototype.next = function() { - if (this.debug) { - this.showlog(); - this.debug = false; - this.nextWithComments().ignoreComments(); - this.debug = true; - } else { - this.nextWithComments().ignoreComments(); - } - return this; -}; - -/** consume comments (if found) **/ -parser.prototype.ignoreComments = function() { - if (this.debug) this.showlog(); - while(this.token === this.tok.T_COMMENT || this.token === this.tok.T_DOC_COMMENT) { - // IGNORE COMMENTS - this.nextWithComments(); - } - return this; -}; - -/** consume the next token (including doc) **/ -parser.prototype.nextWithComments = function() { - this.prev = [ - this.lexer.yylloc.first_line, - this.lexer.yylloc.first_column, - this.lexer.offset - ]; - this.token = this.lexer.lex() || this.EOF; - if (this.debug) this.showlog(); - return this; -}; - -/** - * Check if token is of specified type - */ -parser.prototype.is = function(type) { - if (Array.isArray(type)) { - return type.indexOf(this.token) !== -1; - } else { - return this.entries[type].indexOf(this.token) != -1; - } -}; - -// extends the parser with syntax files -[ - require('./parser/array.js'), - require('./parser/class.js'), - require('./parser/comment.js'), - require('./parser/expr.js'), - require('./parser/function.js'), - require('./parser/if.js'), - require('./parser/loops.js'), - require('./parser/main.js'), - require('./parser/namespace.js'), - require('./parser/scalar.js'), - require('./parser/statement.js'), - require('./parser/switch.js'), - require('./parser/try.js'), - require('./parser/utils.js'), - require('./parser/variable.js') -].forEach(function (ext) { - for(var k in ext) { - parser.prototype[k] = ext[k]; - } -}); - -module.exports = parser; - -},{"./parser/array.js":101,"./parser/class.js":102,"./parser/comment.js":103,"./parser/expr.js":104,"./parser/function.js":105,"./parser/if.js":106,"./parser/loops.js":107,"./parser/main.js":108,"./parser/namespace.js":109,"./parser/scalar.js":110,"./parser/statement.js":111,"./parser/switch.js":112,"./parser/try.js":113,"./parser/utils.js":114,"./parser/variable.js":115}],101:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -var ArrayExpr = 'array'; -var ArrayEntry = 'entry'; - -module.exports = { - /** - * Parse an array - * ```ebnf - * array ::= T_ARRAY '(' array_pair_list ')' | - * '[' array_pair_list ']' - * ``` - */ - read_array: function() { - var expect = null; - var shortForm = false; - var items = []; - var result = this.node(ArrayExpr); - - if (this.token === this.tok.T_ARRAY) { - this.next().expect('('); - expect = ')'; - } else { - shortForm = true; - expect = ']'; - } - - if (this.next().token != expect) { - while(this.token != this.EOF) { - items.push(this.read_array_pair_list()); - if (this.token == ',') { - this.next(); - if (this.token === expect) { - break; - } - } else break; - } - } - this.expect(expect); - this.next(); - return result(shortForm, items); - }, - /** - * Reads an array entry item - * ```ebnf - * array_pair_list ::= '&' w_variable | - * ( - * expr ( - * T_DOUBLE_ARROW ( - * expr | '&' w_variable - * ) - * )? - * ) - * ``` - */ - read_array_pair_list: function() { - var result = this.node(ArrayEntry); - var key = null; - var value = null; - if (this.token === '&') { - value = this.next().read_variable(true, false, true); - } else { - var expr = this.read_expr(); - if (this.token === this.tok.T_DOUBLE_ARROW) { - key = expr; - if (this.next().token === '&') { - value = this.next().read_variable(true, false, true); - } else { - value = this.read_expr(); - } - } else { - value = expr; - } - } - return result(key, value); - }, - /** - * ```ebnf - * dim_offset ::= expr? - * ``` - */ - read_dim_offset: function() { - if (this.token == ']') return false; - return this.read_expr(); - } -}; - -},{}],102:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -module.exports = { - /** - * reading a class - * ```ebnf - * class ::= class_scope? T_CLASS T_STRING (T_EXTENDS NAMESPACE_NAME)? (T_IMPLEMENTS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' CLASS_BODY '}' - * ``` - */ - read_class: function(flag) { - var result = this.node('class'); - this.expect(this.tok.T_CLASS); - this.next().expect(this.tok.T_STRING); - var propName = this.text() - , propExtends = null - , propImplements = null - , body - ; - if (this.next().token == this.tok.T_EXTENDS) { - propExtends = this.next().read_namespace_name(); - } - if (this.token == this.tok.T_IMPLEMENTS) { - propImplements = this.next().read_name_list(); - } - this.expect('{'); - body = this.nextWithComments().read_class_body(); - return result( - propName - ,propExtends - ,propImplements - ,body - ,flag - ); - } - /** - * Read the class visibility - * ```ebnf - * class_scope ::= (T_FINAL | T_ABSTRACT)? - * ``` - */ - ,read_class_scope: function() { - var result = this.token; - if (result == this.tok.T_FINAL) { - this.next(); - return [0, 0, 2]; - } else if (result == this.tok.T_ABSTRACT) { - this.next(); - return [0, 0, 1]; - } - return [0, 0, 0]; - } - /** - * Reads a class body - * ```ebnf - * class_body ::= (member_flags? (T_VAR | T_STRING | T_FUNCTION))* - * ``` - */ - ,read_class_body: function() { - var result = []; - - while(this.token !== this.EOF && this.token !== '}') { - - if (this.token === this.tok.T_COMMENT) { - result.push(this.read_comment()); - continue; - } - - if (this.token === this.tok.T_DOC_COMMENT) { - result.push(this.read_doc_comment()); - continue; - } - - // check T_USE trait - if (this.token === this.tok.T_USE) { - result = result.concat( - this.next().read_trait_use_statement() - ); - continue; - } - - // read member flags - var flags = this.read_member_flags(false); - - // check constant - if (this.token === this.tok.T_CONST) { - var constants = this.read_constant_list(flags); - this.expect(';'); - this.nextWithComments(); - result = result.concat(constants); - continue; - } - - // jump over T_VAR then land on T_VARIABLE - if (this.token === this.tok.T_VAR) { - this.next().expect(this.tok.T_VARIABLE); - flags[0] = flags[1] = 0; // public & non static var - } - - if (this.token === this.tok.T_VARIABLE) { - - // reads a variable - var variables = this.read_variable_list(flags); - this.expect(';'); - this.nextWithComments(); - result = result.concat(variables); - - } else if (this.token === this.tok.T_FUNCTION) { - - // reads a function - result.push(this.read_function(false, flags)); - - } else { - - // raise an error - this.error([ - this.tok.T_CONST, - this.tok.T_VARIABLE, - this.tok.T_FUNCTION - ]); - // ignore token - this.next(); - - } - } - this.expect('}'); - this.nextWithComments(); - return result; - } - /** - * Reads variable list - * ```ebnf - * variable_list ::= (variable_declaration ',')* variable_declaration - * ``` - */ - ,read_variable_list: function(flags) { - return this.read_list( - /** - * Reads a variable declaration - * - * ```ebnf - * variable_declaration ::= T_VARIABLE '=' scalar - * ``` - */ - function read_variable_declaration() { - var result = this.node('property'); - this.expect(this.tok.T_VARIABLE); - var name = this.text().substring(1); // ignore $ - this.next(); - if (this.token === ';' || this.token === ',') { - return result(name, null, flags); - } else if(this.token === '=') { - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L815 - return result(name, this.next().read_expr(), flags); - } else { - this.expect([',', ';', '=']); - return result(name, null, flags); - } - }, ',' - ); - } - /** - * Reads constant list - * ```ebnf - * constant_list ::= T_CONST (constant_declaration ',')* constant_declaration - * ``` - */ - ,read_constant_list: function(flags) { - if (this.expect(this.tok.T_CONST)) { - this.next(); - } - return this.read_list( - /** - * Reads a constant declaration - * - * ```ebnf - * constant_declaration ::= T_STRING '=' expr - * ``` - * @return {Constant} [:link:](AST.md#constant) - */ - function read_constant_declaration() { - var result = this.node('classconstant'), name = null, value = null; - if (this.expect(this.tok.T_STRING)) { - name = this.text(); - this.next(); - } - if (this.expect('=')) { - value = this.next().read_expr(); - } - return result(name, value, flags); - }, ',' - ) - ; - } - /** - * Read member flags - * @return array - * 1st index : 0 => public, 1 => protected, 2 => private - * 2nd index : 0 => instance member, 1 => static member - * 3rd index : 0 => normal, 1 => abstract member, 2 => final member - */ - ,read_member_flags: function(asInterface) { - var result = [-1, -1, -1]; - if (this.is('T_MEMBER_FLAGS')) { - var idx = 0, val = 0; - do { - switch(this.token) { - case this.tok.T_PUBLIC: idx = 0; val = 0; break; - case this.tok.T_PROTECTED: idx = 0; val = 1; break; - case this.tok.T_PRIVATE: idx = 0; val = 2; break; - case this.tok.T_STATIC: idx = 1; val = 1; break; - case this.tok.T_ABSTRACT: idx = 2; val = 1; break; - case this.tok.T_FINAL: idx = 2; val = 2; break; - } - if (asInterface) { - if (idx == 0 && val == 2) { - // an interface can't be private - this.expect([this.tok.T_PUBLIC, this.tok.T_PROTECTED]); - val = -1; - } else if (idx == 2 && val == 1) { - // an interface cant be abstract - this.error(); - val = -1; - } - } - if (result[idx] !== -1) { - // already defined flag - this.error(); - } else if (val !== -1) { - result[idx] = val; - } - } while(this.next().is('T_MEMBER_FLAGS')); - } - - if (result[0] == -1) result[0] = 0; - if (result[1] == -1) result[1] = 0; - if (result[2] == -1) result[2] = 0; - return result; - } - /** - * reading an interface - * ```ebnf - * interface ::= T_INTERFACE T_STRING (T_EXTENDS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' INTERFACE_BODY '}' - * ``` - */ - ,read_interface: function() { - var result = this.node('interface'), name = null, body = null, propExtends = null; - if (this.expect(this.tok.T_INTERFACE)) { - this.next(); - } - if (this.expect(this.tok.T_STRING)) { - name = this.text(); - this.next(); - } - if (this.token === this.tok.T_EXTENDS) { - propExtends = this.next().read_name_list(); - } - if (this.expect('{')) { - body = this.next().read_interface_body(); - } - return result(name, propExtends, body); - } - /** - * Reads an interface body - * ```ebnf - * interface_body ::= (member_flags? (T_CONST | T_FUNCTION))* - * ``` - */ - ,read_interface_body: function() { - var result = []; - - while(this.token !== this.EOF && this.token !== '}') { - - if (this.token === this.tok.T_COMMENT) { - result.push(this.read_comment()); - continue; - } - - if (this.token === this.tok.T_DOC_COMMENT) { - result.push(this.read_doc_comment()); - continue; - } - - // read member flags - var flags = this.read_member_flags(true); - - // check constant - if (this.token == this.tok.T_CONST) { - var constants = this.read_constant_list(flags); - if (this.expect(';')) { - this.nextWithComments(); - } - result = result.concat(constants); - } - - // reads a function - else if (this.token === this.tok.T_FUNCTION) { - var method = this.read_function_declaration(2, flags); - method.parseFlags(flags); - result.push(method); - if (this.expect(';')) { - this.nextWithComments(); - } - } else { - // raise an error - this.error([ - this.tok.T_CONST, - this.tok.T_FUNCTION - ]); - this.next(); - } - } - if (this.expect('}')) { - this.next(); - } - return result; - } - /** - * reading a trait - * ```ebnf - * trait ::= T_TRAIT T_STRING (T_EXTENDS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' FUNCTION* '}' - * ``` - */ - ,read_trait: function(flag) { - var result = this.node('trait'), - propName = null, - propExtends = null, - propImplements = null, - body = null; - if (this.expect(this.tok.T_TRAIT)) { - this.next(); - } - if (this.expect(this.tok.T_STRING)) { - propName = this.text(); - } - if (this.next().token == this.tok.T_EXTENDS) { - propExtends = this.next().read_namespace_name(); - } - if (this.token == this.tok.T_IMPLEMENTS) { - propImplements = this.next().read_name_list(); - } - if (this.expect('{')) { - body = this.next().read_class_body(); - } - return result( - propName, - propExtends, - propImplements, - body - ); - } - /** - * reading a use statement - * ```ebnf - * trait_use_statement ::= namespace_name (',' namespace_name)* ('{' trait_use_alias '}')? - * ``` - */ - ,read_trait_use_statement: function() { - // defines use statements - var node = this.node('traituse'); - var traits = [this.read_namespace_name()]; - var adaptations = null; - while(this.token === ',') { - traits.push( - this.next().read_namespace_name() - ); - } - if (this.token === '{') { - adaptations = []; - // defines alias statements - while(this.next().token !== this.EOF) { - if (this.token === '}') break; - adaptations.push(this.read_trait_use_alias()); - this.expect(';'); - } - if (this.expect('}')) { - this.nextWithComments(); - } - } else { - if (this.expect(';')) { - this.nextWithComments(); - } - } - return node(traits, adaptations); - } - /** - * Reading trait alias - * ```ebnf - * trait_use_alias ::= namespace_name ( T_DOUBLE_COLON T_STRING )? (T_INSTEADOF namespace_name) | (T_AS member_flags? T_STRING) - * ``` - */ - ,read_trait_use_alias: function() { - var node = this.node(); - var trait = null; - var method = this.read_namespace_name(); - - if (this.token === this.tok.T_DOUBLE_COLON) { - if (this.next().expect(this.tok.T_STRING)) { - trait = method; - method = this.text(); - this.next(); - } - } else { - // convert identifier as string - method = method.name; - } - - // handle trait precedence - if (this.token === this.tok.T_INSTEADOF) { - return node( - 'traitprecedence', - trait, method, - this.next().read_name_list() - ); - } - - // handle trait alias - else if (this.token === this.tok.T_AS) { - var flags = false; - var alias = null; - if (this.next().is('T_MEMBER_FLAGS')) { - flags = this.read_member_flags(); - } - - if (this.token === this.tok.T_STRING) { - alias = this.text(); - this.next(); - } else if (flags === false) { - // no visibility flags and no name => too bad - this.expect(this.tok.T_STRING); - } - - return node('traitalias', trait, method, alias, flags) - } - - // handle errors - this.expect([this.tok.T_AS, this.tok.T_INSTEADOF]); - return node('traitalias', trait, method, null, null); - } -}; - -},{}],103:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var docSplit = /^(\s*\*[ \t]*|[ \t]*)(.*)$/gm; - -module.exports = { - /** - * Comments with // or # or / * ... * / - */ - read_comment: function() { - var result = this.node('doc'); - var lines = []; - do { - var line = this.text(); - if (line[0] === '#') { - line = line.substring(1); - } else { - line = line.substring(2); - if (line.substring(line.length - 2) === '*/') { - line = line.substring(0, line.length - 2); - } - } - lines.push(line.trim()); - } while(this.nextWithComments().token === this.tok.T_COMMENT); - return result(false, lines); - }, - /** - * Comments with / ** ... * / - */ - read_doc_comment: function() { - var result = this.node('doc'); - var text = this.text(); - text = text.substring(2, text.length - 2); - var lines = []; - text = text.split(docSplit); - for(var i = 2; i < text.length; i += 3) { - lines.push(text[i].trim()); - } - this.nextWithComments(); - return result(true, lines); - } -}; - -},{}],104:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -module.exports = { - - read_expr: function() { - var result = this.node(); - var expr = this.read_expr_item(); - // binary operations - if (this.token === '|') - return result('bin', '|', expr, this.next().read_expr()); - if (this.token === '&') - return result('bin', '&', expr, this.next().read_expr()); - if (this.token === '^') - return result('bin', '^', expr, this.next().read_expr()); - if (this.token === '.') - return result('bin', '.', expr, this.next().read_expr()); - if (this.token === '+') - return result('bin', '+', expr, this.next().read_expr()); - if (this.token === '-') - return result('bin', '-', expr, this.next().read_expr()); - if (this.token === '*') - return result('bin', '*', expr, this.next().read_expr()); - if (this.token === '/') - return result('bin', '/', expr, this.next().read_expr()); - if (this.token === '%') - return result('bin', '%', expr, this.next().read_expr()); - if (this.token === this.tok.T_POW) - return result('bin', '**', expr, this.next().read_expr()); - if (this.token === this.tok.T_SL) - return result('bin', '<<', expr, this.next().read_expr()); - if (this.token === this.tok.T_SR) - return result('bin', '>>', expr, this.next().read_expr()); - // more binary operations (formerly bool) - if (this.token === this.tok.T_BOOLEAN_OR) - return result('bin', '||', expr, this.next().read_expr()); - if (this.token === this.tok.T_LOGICAL_OR) - return result('bin', 'or', expr, this.next().read_expr()); - if (this.token === this.tok.T_BOOLEAN_AND) - return result('bin', '&&', expr, this.next().read_expr()); - if (this.token === this.tok.T_LOGICAL_AND) - return result('bin', 'and', expr, this.next().read_expr()); - if (this.token === this.tok.T_LOGICAL_XOR) - return result('bin', 'xor', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_IDENTICAL) - return result('bin', '===', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_NOT_IDENTICAL) - return result('bin', '!==', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_EQUAL) - return result('bin', '==', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_NOT_EQUAL) - return result('bin', '!=', expr, this.next().read_expr()); - if (this.token === '<') - return result('bin', '<', expr, this.next().read_expr()); - if (this.token === '>') - return result('bin', '>', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_SMALLER_OR_EQUAL) - return result('bin', '<=', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_GREATER_OR_EQUAL) - return result('bin', '>=', expr, this.next().read_expr()); - if (this.token === this.tok.T_SPACESHIP) - return result('bin', '<=>', expr, this.next().read_expr()); - if (this.token === this.tok.T_INSTANCEOF) - return result('bin', 'instanceof', expr, this.next().read_expr()); - - // extra operations : - // $username = $_GET['user'] ?? 'nobody'; - if (this.token === this.tok.T_COALESCE) - return result('bin', '??', expr, this.next().read_expr()); - - // extra operations : - // $username = $_GET['user'] ? true : false; - if (this.token === '?') { - var trueArg = null; - if (this.next().token !== ':') { - trueArg = this.read_expr(); - } - this.expect(':') && this.next(); - return result('retif', expr, trueArg, this.read_expr()); - } - - return expr; - } - - /** - * ```ebnf - * Reads an expression - * expr ::= @todo - * ``` - */ - ,read_expr_item: function() { - - if (this.token === '@') - return this.node('silent')(this.next().read_expr()); - if (this.token === '+') - return this.node('unary')('+', this.next().read_expr()); - if (this.token === '!') - return this.node('unary')('!', this.next().read_expr()); - if (this.token === '~') - return this.node('unary')('~', this.next().read_expr()); - - if (this.token === '-') { - var result = this.node(); - this.next(); - if ( - this.token === this.tok.T_LNUMBER || - this.token === this.tok.T_DNUMBER - ) { - // negative number - result = result('number', '-' + this.text()); - this.next(); - return result; - } else { - return result('unary', '-', this.read_expr()); - } - } - - if (this.token === '(') { - var node = this.node('parenthesis'); - var expr = this.next().read_expr(); - this.expect(')') && this.next(); - expr = node(expr); - // handle dereferencable - if (this.token === this.tok.T_OBJECT_OPERATOR) { - return this.recursive_variable_chain_scan(expr, false); - } else if (this.token === this.tok.T_CURLY_OPEN || this.token === '[') { - return this.read_dereferencable(expr); - } else if (this.token === '(') { - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118 - return this.node('call')( - expr, this.read_function_argument_list() - ); - } else { - return expr; - } - } - - if (this.token === '`') { - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1048 - return this.next().read_encapsed_string('`'); - } - - if (this.token === this.tok.T_LIST) { - var result = this.node('list'), assign = null; - var isInner = this.innerList; - if (!isInner) { - assign = this.node('assign'); - } - if (this.next().expect('(')) { - this.next(); - } - - if (!this.innerList) this.innerList = true; - var assignList = this.read_assignment_list(); - - // check if contains at least one assignment statement - var hasItem = false; - for(var i = 0; i < assignList.length; i++) { - if (assignList[i] !== null) { - hasItem = true; - break; - } - } - if (!hasItem) { - this.raiseError( - 'Fatal Error : Cannot use empty list on line ' + this.lexer.yylloc.first_line - ); - } - if (this.expect(')')) { - this.next(); - } - - if (!isInner) { - this.innerList = false; - if (this.expect('=')) { - return assign( - result(assignList), - this.next().read_expr(), - '=' - ); - } else { - // fallback : list($a, $b); - return result(assignList); - } - } else { - return result(assignList); - } - } - - if (this.token === this.tok.T_CLONE) - return this.node('clone')( - this.next().read_expr() - ); - - switch(this.token) { - - case this.tok.T_INC: - return this.node('pre')( - '+', this.next().read_variable(false, false, false) - ); - - case this.tok.T_DEC: - return this.node('pre')( - '-', this.next().read_variable(false, false, false) - ); - - case this.tok.T_NEW: - return this.next().read_new_expr(); - - case this.tok.T_ISSET: - var result = this.node('isset'); - if (this.next().expect('(')) { - this.next(); - } - var args = this.read_list(this.read_expr, ','); - if (this.expect(')')) { - this.next(); - } - return result(args); - - case this.tok.T_EMPTY: - var result = this.node('empty'); - if (this.next().expect('(')) { - this.next(); - } - var arg = this.read_expr(); - if (this.expect(')')) { - this.next(); - } - return result([arg]); - - case this.tok.T_INCLUDE: - return this.node('include')( - false, false, - this.next().read_expr() - ); - - case this.tok.T_INCLUDE_ONCE: - return this.node('include')( - true, false, - this.next().read_expr() - ); - - case this.tok.T_REQUIRE: - return this.node('include')( - false, true, - this.next().read_expr() - ); - - case this.tok.T_REQUIRE_ONCE: - return this.node('include')( - true, true, - this.next().read_expr() - ); - - case this.tok.T_EVAL: - var result = this.node('eval'); - if (this.next().expect('(')) { - this.next(); - } - var expr = this.read_expr(); - if (this.expect(')')) { - this.next(); - } - return result(expr); - - case this.tok.T_INT_CAST: - return this.node('cast')('int', this.next().read_expr()); - - case this.tok.T_DOUBLE_CAST: - return this.node('cast')('double', this.next().read_expr()); - - case this.tok.T_STRING_CAST: - return this.node('cast')('string', this.next().read_expr()); - - case this.tok.T_ARRAY_CAST: - return this.node('cast')('array', this.next().read_expr()); - - case this.tok.T_OBJECT_CAST: - return this.node('cast')('object', this.next().read_expr()); - - case this.tok.T_BOOL_CAST: - return this.node('cast')('boolean', this.next().read_expr()); - - case this.tok.T_UNSET_CAST: - return this.node('unset')( - this.next().read_expr() - ); - - case this.tok.T_EXIT: - var result = this.node('exit'); - var status = null; - if ( this.next().token === '(' ) { - if (this.next().token !== ')') { - status = this.read_expr(); - if (this.expect(')')) { - this.next(); - } - } else { - this.next(); - } - } - return result(status); - - case this.tok.T_PRINT: - return this.node('print')( - this.next().read_expr() - ); - - // T_YIELD (expr (T_DOUBLE_ARROW expr)?)? - case this.tok.T_YIELD: - var result = this.node('yield'), value = null, key = null; - if (this.next().is('EXPR')) { - // reads the yield return value - value = this.read_expr(); - if (this.token === this.tok.T_DOUBLE_ARROW) { - // reads the yield returned key - key = value; - value = this.next().read_expr(); - } - } - return result(value, key); - - // T_YIELD_FROM expr - case this.tok.T_YIELD_FROM: - var result = this.node('yieldfrom'); - var expr = this.next().read_expr(); - return result(expr); - - case this.tok.T_FUNCTION: - return this.read_function(true); - - case this.tok.T_STATIC: - var backup = [this.token, this.lexer.getState()]; - if (this.next().token === this.tok.T_FUNCTION) { - // handles static function - return this.read_function(true, [0, 1, 0]); - } else { - // rollback - this.lexer.tokens.push(backup); - this.next(); - } - - - } - - // SCALAR | VARIABLE - var expr; - if (this.is('VARIABLE')) { - var result = this.node(); - expr = this.read_variable(false, false, false); - - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L877 - // should accept only a variable - var isConst = ( - expr.kind === 'constref' || ( - expr.kind === 'staticlookup' && - expr.offset.kind === 'constref' - ) - ); - - // VARIABLES SPECIFIC OPERATIONS - switch(this.token) { - case '=': - if (isConst) this.error('VARIABLE'); - var right; - if (this.next().token == '&') { - if (this.next().token === this.tok.T_NEW) { - right = this.next().read_new_expr(); - } else { - right = this.read_variable(false, false, true); - } - } else { - right = this.read_expr(); - } - return result('assign', expr, right, '='); - - // operations : - case this.tok.T_PLUS_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '+='); - - case this.tok.T_MINUS_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '-='); - - case this.tok.T_MUL_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '*='); - - case this.tok.T_POW_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '**='); - - case this.tok.T_DIV_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '/='); - - case this.tok.T_CONCAT_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '.='); - - case this.tok.T_MOD_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '%='); - - case this.tok.T_AND_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '&='); - - case this.tok.T_OR_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '|='); - - case this.tok.T_XOR_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '^='); - - case this.tok.T_SL_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '<<='); - - case this.tok.T_SR_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign',expr, this.next().read_expr(), '>>='); - - case this.tok.T_INC: - if (isConst) this.error('VARIABLE'); - this.next(); - return result('post', '+', expr); - case this.tok.T_DEC: - if (isConst) this.error('VARIABLE'); - this.next(); - return result('post', '-', expr); - } - } else if (this.is('SCALAR')) { - expr = this.read_scalar(); - // handle dereferencable - while(this.token !== this.EOF) { - if (this.token === this.tok.T_OBJECT_OPERATOR) { - expr = this.recursive_variable_chain_scan(expr, false); - } else if (this.token === this.tok.T_CURLY_OPEN || this.token === '[') { - expr = this.read_dereferencable(expr); - } else if (this.token === '(') { - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118 - expr = this.node('call')(expr, this.read_function_argument_list()); - } else { - return expr; - } - } - } else { - this.error('EXPR'); - this.next(); - } - - // returns variable | scalar - return expr; - - } - /** - * ```ebnf - * new_expr ::= T_NEW (namespace_name function_argument_list) | (T_CLASS ... class declaration) - * ``` - * https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L850 - */ - ,read_new_expr: function() { - var result = this.node('new'); - if (this.token === this.tok.T_CLASS) { - var what = this.node('class'); - // Annonymous class declaration - var propExtends = null, propImplements = null, body = null, args = []; - if (this.next().token === '(') { - args = this.read_function_argument_list(); - } - if (this.token == this.tok.T_EXTENDS) { - propExtends = this.next().read_namespace_name(); - } - if (this.token == this.tok.T_IMPLEMENTS) { - propImplements = this.next().read_name_list(); - } - if (this.expect('{')) { - body = this.next().read_class_body(); - } - return result( - what( - null - ,propExtends - ,propImplements - ,body - ,[0, 0, 0] - ), args - ); - } else { - // Already existing class - var name = this.read_class_name_reference(); - var args = []; - if (this.token === '(') { - args = this.read_function_argument_list(); - } - return result(name, args); - } - } - /** - * Reads a class name - * ```ebnf - * class_name_reference ::= namespace_name | variable - * ``` - */ - ,read_class_name_reference: function() { - if ( - this.token === this.tok.T_NS_SEPARATOR || - this.token === this.tok.T_STRING || - this.token === this.tok.T_NAMESPACE - ) { - var result = this.read_namespace_name(); - if (this.token === this.tok.T_DOUBLE_COLON) { - result = this.read_static_getter(result); - } - return result; - } else if (this.is('VARIABLE')) { - return this.read_variable(true, false, false); - } else { - this.expect([this.tok.T_STRING, 'VARIABLE']); - } - } - /** - * ```ebnf - * assignment_list ::= assignment_list_element (',' assignment_list_element?)* - * ``` - */ - ,read_assignment_list: function() { - return this.read_list( - this.read_assignment_list_element, ',' - ); - } - - /** - * ```ebnf - * assignment_list_element ::= expr | expr T_DOUBLE_ARROW expr - * ``` - */ - ,read_assignment_list_element: function() { - if (this.token === ',' || this.token === ')') return null; - var result = this.read_expr_item(); - if (this.token === this.tok.T_DOUBLE_ARROW) { - result = [ - 'key', - result, - this.next().read_expr_item() - ]; - } - return result; - } -}; - -},{}],105:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -module.exports = { - /** - * checks if current token is a reference keyword - */ - is_reference: function() { - if (this.token == '&') { - this.next(); - return true; - } - return false; - } - /** - * checks if current token is a variadic keyword - */ - ,is_variadic: function() { - if (this.token === this.tok.T_ELLIPSIS) { - this.next(); - return true; - } - return false; - } - /** - * reading a function - * ```ebnf - * function ::= function_declaration code_block - * ``` - */ - ,read_function: function(closure, flag) { - var result = this.read_function_declaration( - closure ? 1 : (flag ? 2 : 0), - flag && flag[1] === 1 - ); - if (flag && flag[2] == 1) { - // abstract function : - result.parseFlags(flag); - if (this.expect(';')) { - this.nextWithComments(); - } - } else { - if (this.expect('{')) { - result.body = this.read_code_block(false); - if (result.loc && result.body.loc) { - result.loc.end = result.body.loc.end; - } - } - if (!closure && flag) { - result.parseFlags(flag); - } - } - return result; - } - /** - * reads a function declaration (without his body) - * ```ebnf - * function_declaration ::= T_FUNCTION '&'? T_STRING '(' parameter_list ')' - * ``` - */ - ,read_function_declaration: function(type, isStatic) { - var nodeName = 'function'; - if (type === 1) { - nodeName = 'closure'; - } else if (type === 2) { - nodeName = 'method'; - } - var result = this.node(nodeName); - - if (this.expect(this.tok.T_FUNCTION)) { - this.next(); - } - var isRef = this.is_reference(); - var name = false, use = [], returnType = null, nullable = false; - if (type !== 1) { - if (this.expect(this.tok.T_STRING)) { - name = this.text(); - this.next(); - } - } - if (this.expect('(')) this.next(); - var params = this.read_parameter_list(); - if (this.expect(')')) this.next(); - if (type === 1 && this.token === this.tok.T_USE) { - if (this.next().expect('(')) this.next(); - use = this.read_list(this.read_lexical_var, ','); - if (this.expect(')')) this.next(); - } - if (this.token === ':') { - if (this.next().token === '?') { - nullable = true; - this.next(); - } - returnType = this.read_type(); - } - if (type === 1) { - // closure - return result(params, isRef, use, returnType, nullable, isStatic); - } - return result(name, params, isRef, returnType, nullable); - } - /** - * ```ebnf - * lexical_var ::= '&'? T_VARIABLE - * ``` - */ - ,read_lexical_var: function() { - var result = this.node('variable'); - var isRef = false; - if (this.token === '&') { - isRef = true; - this.next(); - } - this.expect(this.tok.T_VARIABLE); - var name = this.text().substring(1); - this.next(); - return result(name, isRef, false); - } - /** - * reads a list of parameters - * ```ebnf - * parameter_list ::= (parameter ',')* parameter? - * ``` - */ - ,read_parameter_list: function() { - var result = []; - if (this.token != ')') { - while(this.token != this.EOF) { - result.push(this.read_parameter()); - if (this.token == ',') { - this.next(); - } else if (this.token == ')') { - break; - } else { - this.error([',', ')']); - break; - } - } - } - return result; - } - /** - * ```ebnf - * parameter ::= type? '&'? T_ELLIPSIS? T_VARIABLE ('=' expr)? - * ``` - * @see https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L640 - */ - ,read_parameter: function() { - var node = this.node('parameter'), - name = null, - value = null, - type = null, - nullable = false; - if (this.token === '?') { - this.next(); - nullable = true; - } - type = this.read_type(); - if (nullable && !type) { - this.raiseError('Expecting a type definition combined with nullable operator'); - } - var isRef = this.is_reference(); - var isVariadic = this.is_variadic(); - if (this.expect(this.tok.T_VARIABLE)) { - name = this.text().substring(1); - this.next(); - } - if (this.token == '=') { - value = this.next().read_expr(); - } - return node(name, type, value, isRef, isVariadic, nullable); - } - /** - * Reads a list of arguments - * ```ebnf - * function_argument_list ::= '(' (argument_list (',' argument_list)*)? ')' - * ``` - */ - ,read_function_argument_list: function() { - var result = []; - var wasVariadic = false; - this.expect('(') && this.next(); - if (this.token !== ')') { - while(this.token != this.EOF) { - var argument = this.read_argument_list(); - if (argument) { - result.push(argument); - if (argument.kind === 'variadic') { - wasVariadic = true; - } else if (wasVariadic) { - this.raiseError('Unexpected argument after a variadic argument'); - } - } - if (this.token === ',') { - this.next(); - } else break; - } - } - this.expect(')') && this.next(); - return result; - } - /** - * ```ebnf - * argument_list ::= T_ELLIPSIS? expr - * ``` - */ - ,read_argument_list: function() { - if (this.token === this.tok.T_ELLIPSIS ) { - return this.node('variadic')(this.next().read_expr()); - } - return this.read_expr(); - } - /** - * read type hinting - * ```ebnf - * type ::= T_ARRAY | T_CALLABLE | namespace_name - * ``` - */ - ,read_type: function() { - var result = this.node('identifier'); - switch(this.token) { - case this.tok.T_ARRAY: - this.next(); - return result(['', 'array'], false); - case this.tok.T_NAMESPACE: - case this.tok.T_NS_SEPARATOR: - case this.tok.T_STRING: - return this.read_namespace_name(); - case this.tok.T_CALLABLE: - this.next(); - return result(['', 'callable'], false); - default: - return null; - } - } -}; - -},{}],106:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -module.exports = { - /** - * Reads an IF statement - * - * ```ebnf - * if ::= T_IF '(' expr ')' ':' ... - * ``` - */ - read_if: function() { - var result = this.node('if'), - body = null, - alternate = null, - shortForm = false, - test = null; - test = this.read_if_expr(); - - if (this.token === ':') { - shortForm = true; - this.next(); - body = this.node('block'); - var items = []; - while(this.token !== this.EOF && this.token !== this.tok.T_ENDIF) { - if (this.token === this.tok.T_ELSEIF) { - alternate = this.next().read_elseif_short(); - break; - } else if (this.token === this.tok.T_ELSE) { - alternate = this.next().read_else_short(); - break; - } - items.push(this.read_inner_statement()); - } - body = body(null, items); - this.expect(this.tok.T_ENDIF) && this.next(); - this.expectEndOfStatement(); - } else { - body = this.read_statement(); - /** - * ignore : if (..) { } /* *./ else { } - */ - this.ignoreComments(); - if (this.token === this.tok.T_ELSEIF) { - alternate = this.next().read_if(); - } else if (this.token === this.tok.T_ELSE) { - alternate = this.next().read_statement(); - } - } - return result(test, body, alternate, shortForm); - }, - /** - * reads an if expression : '(' expr ')' - */ - read_if_expr: function() { - this.expect('(') && this.next(); - var result = this.read_expr(); - this.expect(')') && this.next(); - return result; - }, - /** - * reads an elseif (expr): statements - */ - read_elseif_short: function() { - var result = this.node('if'), - alternate = null, - test = null, - body = null, - items = []; - test = this.read_if_expr(); - if (this.expect(':')) this.next(); - body = this.node('block'); - while(this.token != this.EOF && this.token !== this.tok.T_ENDIF) { - if (this.token === this.tok.T_ELSEIF) { - alternate = this.next().read_elseif_short(); - break; - } else if (this.token === this.tok.T_ELSE) { - alternate = this.next().read_else_short(); - break; - } - items.push(this.read_inner_statement()); - } - body = body(null, items); - return result(test, body, alternate, true); - }, - /** - * - */ - read_else_short: function() { - if (this.expect(':')) this.next(); - var body = this.node('block'), items = []; - while(this.token != this.EOF && this.token !== this.tok.T_ENDIF) { - items.push(this.read_inner_statement()); - } - return body(null, items); - } -}; - -},{}],107:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; -module.exports = { - /** - * Reads a while statement - * ```ebnf - * while ::= T_WHILE (statement | ':' inner_statement_list T_ENDWHILE ';') - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L587 - * @return {While} - */ - read_while: function() { - var result = this.node('while'), - test = null, - body = null, - shortForm = false - ; - if (this.expect('(')) this.next(); - test = this.read_expr(); - if (this.expect(')')) this.next(); - if (this.token === ':') { - shortForm = true; - body = this.read_short_form(this.tok.T_ENDWHILE); - } else { - body = this.read_statement(); - } - return result(test, body, shortForm); - } - /** - * Reads a do / while loop - * ```ebnf - * do ::= T_DO statement T_WHILE '(' expr ')' ';' - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L423 - * @return {Do} - */ - ,read_do: function() { - var result = this.node('do'), - test = null, - body = null - ; - body = this.read_statement(); - if (this.ignoreComments().expect(this.tok.T_WHILE)) { - if (this.next().expect('(')) this.next(); - test = this.read_expr(); - if (this.expect(')')) this.next(); - if (this.expect(';')) this.next(); - } - return result(test, body); - } - /** - * Read a for incremental loop - * ```ebnf - * for ::= T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement - * for_statement ::= statement | ':' inner_statement_list T_ENDFOR ';' - * for_exprs ::= expr? (',' expr)* - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L425 - * @return {For} - */ - ,read_for: function() { - var result = this.node('for'), - init = [], - test = [], - increment = [], - body = null, - shortForm = false; - if (this.expect('(')) this.next(); - if (this.token !== ';') { - init = this.read_list(this.read_expr, ','); - if (this.expect(';')) this.next(); - } else { - this.next(); - } - if (this.token !== ';') { - test = this.read_list(this.read_expr, ','); - if (this.expect(';')) this.next(); - } else { - this.next(); - } - if (this.token !== ')') { - increment = this.read_list(this.read_expr, ','); - if (this.expect(')')) this.next(); - } else { - this.next(); - } - if (this.token === ':') { - shortForm = true; - body = this.read_short_form(this.tok.T_ENDFOR); - } else { - body = this.read_statement(); - } - return result(init, test, increment, body, shortForm); - } - /** - * Reads a foreach loop - * ```ebnf - * foreach ::= '(' expr T_AS foreach_variable (T_DOUBLE_ARROW foreach_variable)? ')' statement - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L438 - * @return {Foreach} - */ - ,read_foreach: function() { - var result = this.node('foreach'), - source = null, - key = null, - value = null, - body = null, - shortForm = false; - if (this.expect('(')) this.next(); - source = this.read_expr(); - if (this.ignoreComments().expect(this.tok.T_AS)) { - this.next(); - value = this.read_foreach_variable(); - if (this.token === this.tok.T_DOUBLE_ARROW) { - key = value; - value = this.next().read_foreach_variable(); - } - } - - if (this.expect(')')) this.next(); - - if (this.token === ':') { - shortForm = true; - body = this.read_short_form(this.tok.T_ENDFOREACH); - } else { - body = this.read_statement(); - } - return result(source, key, value, body, shortForm); - } - /** - * Reads a foreach variable statement - * ```ebnf - * foreach_variable = variable | - * T_LIST '(' assignment_list ')' | - * '[' array_pair_list ']' - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L544 - * @return {Expression} - */ - ,read_foreach_variable: function() { - if (this.token === this.tok.T_LIST) { - var result = this.node('list'); - if (this.next().expect('(')) this.next(); - var assignList = this.read_assignment_list(); - if (this.expect(')')) this.next(); - return result(assignList); - } else if (this.token === '[' || this.token === this.tok.T_ARRAY) { - return this.read_array(); - } else { - return this.read_variable(false, false, false); - } - } -}; - -},{}],108:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -module.exports = { - /** - * ```ebnf - * start ::= (namespace | top_statement)* - * ``` - */ - read_start: function() { - if (this.token == this.tok.T_NAMESPACE) { - return this.read_namespace(); - } else { - return this.read_top_statement(); - } - } -}; - -},{}],109:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -module.exports = { - /** - * Reads a namespace declaration block - * ```ebnf - * namespace ::= T_NAMESPACE namespace_name? '{' - * top_statements - * '}' - * | T_NAMESPACE namespace_name ';' top_statements - * ``` - * @see http://php.net/manual/en/language.namespaces.php - * @return {Namespace} - */ - read_namespace: function() { - var result = this.node('namespace'); - this.expect(this.tok.T_NAMESPACE) && this.next(); - if (this.token == '{') { - this.currentNamespace = ['']; - var body = this.nextWithComments().read_top_statements(); - this.expect('}') && this.nextWithComments(); - return result([''], body, true); - } else { - var name = this.read_namespace_name(); - if (this.token == ';') { - this.currentNamespace = name; - var body = this.nextWithComments().read_top_statements(); - this.expect(this.EOF); - return result(name.name, body, false); - } else if (this.token == '{') { - this.currentNamespace = name; - var body = this.nextWithComments().read_top_statements(); - this.expect('}') && this.nextWithComments(); - return result(name.name, body, true); - } else if (this.token === '(') { - // resolve ambuiguity between namespace & function call - name.resolution = this.ast.identifier.RELATIVE_NAME; - name.name = name.name.substring(1); - return this.node('call')( - name, this.read_function_argument_list() - ); - } else { - this.error(['{', ';']); - // graceful mode : - this.currentNamespace = name; - var body = this.read_top_statements(); - this.expect(this.EOF); - return result(name, body, false); - } - } - } - /** - * Reads a namespace name - * ```ebnf - * namespace_name ::= T_NS_SEPARATOR? (T_STRING T_NS_SEPARATOR)* T_STRING - * ``` - * @see http://php.net/manual/en/language.namespaces.rules.php - * @return {Identifier} - */ - ,read_namespace_name: function() { - var result = this.node('identifier'), relative = false; - if (this.token === this.tok.T_NAMESPACE) { - this.next().expect(this.tok.T_NS_SEPARATOR) && this.next(); - relative = true - } - return result( - this.read_list(this.tok.T_STRING, this.tok.T_NS_SEPARATOR, true), - relative - ); - } - /** - * Reads a use statement - * ```ebnf - * use_statement ::= T_USE - * use_type? use_declarations | - * use_type use_statement '{' use_declarations '}' | - * use_statement '{' use_declarations(=>typed) '}' - * ';' - * ``` - * @see http://php.net/manual/en/language.namespaces.importing.php - * @return {UseGroup} - */ - ,read_use_statement: function() { - var result = this.node('usegroup'), - type = null, - items = [], - name = null - ; - this.expect(this.tok.T_USE) && this.next(); - type = this.read_use_type(); - items.push(this.read_use_declaration(false)); - if (this.token === ',') { - items = items.concat(this.next().read_use_declarations(false)); - } else if (this.token === '{') { - name = items[0].name; - items = this.next().read_use_declarations(type === null); - this.expect('}') && this.next(); - } - this.expect(';') && this.nextWithComments(); - return result(name, type, items); - } - /** - * Reads a use declaration - * ```ebnf - * use_declaration ::= use_type? namespace_name use_alias - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L380 - * @return {UseItem} - */ - ,read_use_declaration: function(typed) { - var result = this.node('useitem'), type = null; - if (typed) type = this.read_use_type(); - var name = this.read_namespace_name(); - var alias = this.read_use_alias(); - return result(name.name, alias, type); - } - /** - * Reads a list of use declarations - * ```ebnf - * use_declarations ::= use_declaration (',' use_declaration)* - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L380 - * @return {UseItem[]} - */ - ,read_use_declarations: function(typed) { - var result = [this.read_use_declaration(typed)]; - while(this.token === ',') { - result.push(this.next().read_use_declaration(typed)); - } - return result; - } - /** - * Reads a use statement - * ```ebnf - * use_alias ::= (T_AS T_STRING)? - * ``` - * @return {String|null} - */ - ,read_use_alias: function() { - var result = null; - if (this.token === this.tok.T_AS) { - if (this.next().expect(this.tok.T_STRING)) { - result = this.text(); - this.next(); - } - } - return result; - } - /** - * Reads the namespace type declaration - * ```ebnf - * use_type ::= (T_FUNCTION | T_CONST)? - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L335 - * @return {String|null} Possible values : function, const - */ - ,read_use_type: function() { - if (this.token === this.tok.T_FUNCTION) { - this.next(); - return this.ast.useitem.TYPE_FUNCTION; - } else if (this.token === this.tok.T_CONST) { - this.next(); - return this.ast.useitem.TYPE_CONST; - } - return null; - } -}; - -},{}],110:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var specialChar = { - '\\r': "\r", - '\\n': "\n", - '\\t': "\t", - '\\v': String.fromCharCode(11), - '\\e': String.fromCharCode(27), - '\\f': String.fromCharCode(12), - "\\\\": "\\", - '\\$': "$", - '\\"': '"', - '\\\'': "'" -}; - -module.exports = { - /** - * Unescape special chars - */ - resolve_special_chars: function(text) { - return text.replace( - /\\[rntvef"'\\\$]/g, - function(seq) { - return specialChar[seq]; - } - ); - }, - /** - * ```ebnf - * scalar ::= T_MAGIC_CONST - * | T_LNUMBER | T_DNUMBER - * | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE? T_END_HEREDOC - * | '"' encaps_list '"' - * | T_START_HEREDOC encaps_list T_END_HEREDOC - * | namespace_name (T_DOUBLE_COLON T_STRING)? - * ``` - */ - read_scalar: function() { - if (this.is('T_MAGIC_CONST')) { - return this.get_magic_constant(); - } else { - switch(this.token) { - - // TEXTS - case this.tok.T_CONSTANT_ENCAPSED_STRING: - var value = this.node('string'); - var text = this.text(); - var isDoubleQuote = text[0] === '"'; - text = text.substring(1, text.length - 1); - this.next(); - value = value(isDoubleQuote, this.resolve_special_chars(text)); - if (this.token === this.tok.T_DOUBLE_COLON) { - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1151 - return this.read_static_getter(value); - } else { - // dirrect string - return value; - } - case this.tok.T_START_HEREDOC: - if (this.lexer.curCondition === 'ST_NOWDOC') { - var node = this.node('nowdoc'); - var value = this.next().text(); - // strip the last line return char - var lastCh = value[value.length-1]; - if (lastCh === '\n') { - if (value[value.length-2] === '\r') { - // windows style - value = value.substring(0, value.length - 2); - } else { - // linux style - value = value.substring(0, value.length - 1); - } - } else if (lastCh === '\r') { - // mac style - value = value.substring(0, value.length - 1); - } - this.expect(this.tok.T_ENCAPSED_AND_WHITESPACE) && this.next(); - node = node(value, this.lexer.heredoc_label); - this.expect(this.tok.T_END_HEREDOC) && this.next(); - return node; - } else { - return this.next().read_encapsed_string( - this.tok.T_END_HEREDOC - ); - } - - case '"': - return this.next().read_encapsed_string('"'); - - case 'b"': - case 'B"': - var node = this.node('cast'); - var what = this.next().read_encapsed_string('"'); - return node('binary', what); - - // NUMERIC - case this.tok.T_LNUMBER: // long - case this.tok.T_DNUMBER: // double - var result = this.node('number'); - var value = this.text(); - this.next(); - result = result(value); - return result; - - // ARRAYS - case this.tok.T_ARRAY: // array parser - case '[': // short array format - return this.read_array(); - default: - var err = this.error('SCALAR'); - // graceful mode : ignore token & return error node - this.next(); - return err; - } - } - } - /** - * Handles the dereferencing - */ - ,read_dereferencable: function(expr) { - var result; - var node = this.node('offsetlookup'); - if (this.token === '[') { - var offset = this.next().read_expr(); - if (this.expect(']')) this.next(); - result = node(expr, offset); - } else if (this.token === this.tok.T_DOLLAR_OPEN_CURLY_BRACES) { - var offset = this.read_encapsed_string_item(); - result = node(expr, offset); - } - return result; - } - /** - * Reads and extracts an encapsed item - * ```ebnf - * encapsed_string_item ::= T_ENCAPSED_AND_WHITESPACE - * | T_DOLLAR_OPEN_CURLY_BRACES expr '}' - * | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' - * | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' - * | T_CURLY_OPEN variable '}' - * | variable - * | variable '[' expr ']' - * | variable T_OBJECT_OPERATOR T_STRING - * ``` - * @return {String|Variable|Expr|Lookup} - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1219 - */ - ,read_encapsed_string_item: function() { - var result = this.node(); - - // plain text - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1222 - if (this.token === this.tok.T_ENCAPSED_AND_WHITESPACE) { - var text = this.text(); - this.next(); - result = result( - 'string', false, this.resolve_special_chars(text) - ); - } - - // dynamic variable name - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1239 - else if (this.token === this.tok.T_DOLLAR_OPEN_CURLY_BRACES) { - var name = null; - if (this.next().token === this.tok.T_STRING_VARNAME) { - var varName = this.text(); - name = this.node('variable'); - this.next(); - // check if lookup an offset - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1243 - if (this.token === '[') { - name = name(varName, false); - var node = this.node('offsetlookup'); - var offset = this.next().read_expr(); - this.expect(']') && this.next(); - name = node(name, offset); - } else { - name = varName; - } - } else { - name = this.read_expr(); - } - this.expect('}') && this.next(); - result = result('variable', name, false, true); - } - - // expression - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1246 - else if (this.token === this.tok.T_CURLY_OPEN) { - result = this.next().read_variable(false, false, false); - this.expect('}') && this.next(); - } - - // plain variable - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1231 - else if (this.token === this.tok.T_VARIABLE) { - result = this.read_simple_variable(false); - - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1233 - if (this.token === '[') { - var node = this.node('offsetlookup'); - var offset = this.next().read_encaps_var_offset(); - this.expect(']') && this.next(); - result = node(result, offset); - } - - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1236 - if (this.token === this.tok.T_OBJECT_OPERATOR) { - var node = this.node('propertylookup'); - var what = this.node('constref'); - this.next().expect(this.tok.T_STRING); - var name = this.text(); - this.next(); - result = node(result, what(name)); - } - - // error / fallback - } else { - this.expect(this.tok.T_ENCAPSED_AND_WHITESPACE); - var value = this.text(); - this.next(); - // consider it as string - result = result('string', false, value); - } - - return result; - } - /** - * Reads an encapsed string - */ - ,read_encapsed_string: function(expect) { - var node = this.node('encapsed'), value = [], type = null; - - if (expect === '`') { - type = this.ast.encapsed.TYPE_SHELL; - } else if (expect === '"') { - type = this.ast.encapsed.TYPE_STRING; - } else { - type = this.ast.encapsed.TYPE_HEREDOC; - } - - // reading encapsed parts - while(this.token !== expect && this.token !== this.EOF) { - value.push(this.read_encapsed_string_item()); - } - - this.expect(expect) && this.next(); - node = node(value, type); - - if (expect === this.tok.T_END_HEREDOC) { - node.label = this.lexer.heredoc_label; - } - return node; - } - /** - * Constant token - */ - ,get_magic_constant: function() { - var result = this.node('magic'); - var name = this.text(); - this.next(); - return result(name); - } -}; - -},{}],111:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -module.exports = { - /** - * reading a list of top statements (helper for top_statement*) - * ```ebnf - * top_statements ::= top_statement* - * ``` - */ - read_top_statements: function() { - var result = []; - while(this.token !== this.EOF && this.token !== '}') { - var statement = this.read_top_statement(); - if (statement) { - if (Array.isArray(statement)) { - result = result.concat(statement); - } else { - result.push(statement); - } - } - } - return result; - } - /** - * reading a top statement - * ```ebnf - * top_statement ::= - * namespace | function | class - * | interface | trait - * | use_statements | const_list - * | statement - * ``` - */ - ,read_top_statement: function() { - switch(this.token) { - case this.tok.T_FUNCTION: - return this.read_function(false, false); - // optional flags - case this.tok.T_ABSTRACT: - case this.tok.T_FINAL: - var flag = this.read_class_scope(); - if (this.token === this.tok.T_CLASS) { - return this.read_class(flag); - } else { - this.error(this.tok.T_CLASS); - this.next(); - return null; - } - case this.tok.T_CLASS: - return this.read_class([0, 0, 0]); - case this.tok.T_INTERFACE: - return this.read_interface(); - case this.tok.T_TRAIT: - return this.read_trait(); - case this.tok.T_USE: - return this.read_use_statement(); - case this.tok.T_CONST: - return this.next().read_const_list(); - case this.tok.T_NAMESPACE: - return this.read_namespace(); - case this.tok.T_HALT_COMPILER: - var result = this.node('halt'); - if (this.next().expect('(')) this.next(); - if (this.expect(')')) this.next(); - this.expect(';'); - this.lexer.done = true; - return result(this.lexer._input.substring( - this.lexer.offset - )); - default: - return this.read_statement(); - } - } - /** - * reads a list of simple inner statements (helper for inner_statement*) - * ```ebnf - * inner_statements ::= inner_statement* - * ``` - */ - ,read_inner_statements: function() { - var result = []; - while(this.token != this.EOF && this.token !== '}') { - var statement = this.read_inner_statement(); - if (statement) { - if (Array.isArray(statement)) { - result = result.concat(statement); - } else { - result.push(statement); - } - } - } - return result; - } - /** - * Reads a list of constants declaration - * ```ebnf - * const_list ::= T_CONST T_STRING '=' expr (',' T_STRING '=' expr)* ';' - * ``` - */ - ,read_const_list: function() { - var result = this.read_list(function() { - this.expect(this.tok.T_STRING); - var result = this.node('constant'); - var name = this.text(); - if (this.next().expect('=')) { - return result(name, this.next().read_expr()); - } else { - // fallback - return result(name, null); - } - }, ',', false); - this.expectEndOfStatement(); - return result; - } - /** - * Reads a list of constants declaration - * ```ebnf - * declare_list ::= T_STRING '=' expr (',' T_STRING '=' expr)* - * ``` - * @retrurn {Object} - */ - ,read_declare_list: function() { - var result = {}; - while(this.token != this.EOF && this.token !== ')') { - this.expect(this.tok.T_STRING); - var name = this.text().toLowerCase(); - if (this.next().expect('=')) { - result[name] = this.next().read_expr(); - } else { - result[name] = null; - } - if (this.token !== ',') break; - this.next(); - } - return result; - } - /** - * reads a simple inner statement - * ```ebnf - * inner_statement ::= '{' inner_statements '}' | token - * ``` - */ - ,read_inner_statement: function() { - switch(this.token) { - case this.tok.T_FUNCTION: - return this.read_function(false, false); - // optional flags - case this.tok.T_ABSTRACT: - case this.tok.T_FINAL: - var flag = this.read_class_scope(); - if (this.token === this.tok.T_CLASS) { - return this.read_class(flag); - } else { - this.error(this.tok.T_CLASS); - // graceful mode : ignore token & go next - this.next(); - return null; - } - case this.tok.T_CLASS: - return this.read_class([0, 0, 0]); - case this.tok.T_INTERFACE: - return this.read_interface(); - case this.tok.T_TRAIT: - return this.read_trait(); - case this.tok.T_HALT_COMPILER: - this.raiseError( - '__HALT_COMPILER() can only be used from the outermost scope' - ); - // fallback : returns a node but does not stop the parsing - var node = this.node('halt'); - this.next().expect('(') && this.next(); - this.expect(')') && this.next(); - node = node(this.lexer._input.substring( - this.lexer.offset - )); - this.expect(';') && this.next(); - return node; - default: - return this.read_statement(); - } - } - /** - * Reads statements - */ - ,read_statement: function() { - - switch(this.token) { - - case '{': return this.read_code_block(false); - - case this.tok.T_IF: return this.next().read_if(); - - case this.tok.T_SWITCH: return this.read_switch(); - - case this.tok.T_FOR: return this.next().read_for(); - - case this.tok.T_FOREACH: return this.next().read_foreach(); - - case this.tok.T_WHILE: return this.next().read_while(); - - case this.tok.T_DO: return this.next().read_do(); - - case this.tok.T_COMMENT: return this.read_comment(); - - case this.tok.T_DOC_COMMENT: return this.read_doc_comment(); - - case this.tok.T_RETURN: - var result = this.node('return'), expr = null; - if (!this.next().is('EOS')) { - expr = this.read_expr(); - } - this.expectEndOfStatement(); - return result(expr); - - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L429 - case this.tok.T_BREAK: - case this.tok.T_CONTINUE: - var result = this.node( - this.token === this.tok.T_CONTINUE ? 'continue' : 'break' - ), level = null; - this.next(); // look ahead - if (this.token !== ';' && this.token !== this.tok.T_CLOSE_TAG) { - level = this.read_expr(); - } - this.expectEndOfStatement(); - return result(level); - - case this.tok.T_GLOBAL: - var result = this.node('global'); - var items = this.next().read_list(this.read_simple_variable, ','); - this.expectEndOfStatement(); - return result(items); - - case this.tok.T_STATIC: - var current = [this.token, this.lexer.getState()]; - var result = this.node('static'); - if (this.next().token === this.tok.T_DOUBLE_COLON) { - // static keyword for a class - this.lexer.tokens.push(current); - var expr = this.next().read_expr(); - this.expect(';') && this.nextWithComments(); - return expr; - } - if (this.token === this.tok.T_FUNCTION) { - return this.read_function(true, [0, 1, 0]); - } - var items = this.read_variable_declarations(); - this.expectEndOfStatement(); - return result(items); - - case this.tok.T_ECHO: - var result = this.node('echo'); - var args = this.next().read_list(this.read_expr, ','); - this.expectEndOfStatement(); - return result(args); - - case this.tok.T_INLINE_HTML: - var result = this.node('inline'), value = this.text(); - this.next(); - return result(value); - - case this.tok.T_UNSET: - var result = this.node('unset'); - this.next().expect('(') && this.next(); - var items = this.read_list(this.read_variable, ','); - this.expect(')') && this.next(); - this.expect(';') && this.nextWithComments(); - return result(items); - - case this.tok.T_DECLARE: - var result = this.node('declare'), - what, - body = [], - mode; - this.next().expect('(') && this.next(); - what = this.read_declare_list(); - this.expect(')') && this.next(); - if (this.token === ':') { - this.nextWithComments(); - while(this.token != this.EOF && this.token !== this.tok.T_ENDDECLARE) { - // @todo : check declare_statement from php / not valid - body.push(this.read_top_statement()); - } - this.expect(this.tok.T_ENDDECLARE) && this.next(); - this.expectEndOfStatement(); - mode = this.ast.declare.MODE_SHORT; - } else if (this.token === '{') { - this.nextWithComments(); - while(this.token != this.EOF && this.token !== '}') { - // @todo : check declare_statement from php / not valid - body.push(this.read_top_statement()); - } - this.expect('}') && this.next(); - mode = this.ast.declare.MODE_BLOCK; - } else { - this.expect(';') && this.nextWithComments(); - while(this.token != this.EOF && this.token !== this.tok.T_DECLARE) { - // @todo : check declare_statement from php / not valid - body.push(this.read_top_statement()); - } - mode = this.ast.declare.MODE_NONE; - } - return result(what, body, mode); - - case this.tok.T_TRY: - return this.read_try(); - - case this.tok.T_THROW: - var result = this.node('throw'); - var expr = this.next().read_expr(); - this.expectEndOfStatement(); - return result(expr); - - case ';': // ignore this (extra ponctuation) - case this.tok.T_CLOSE_TAG: // empty tag - this.next(); - return null; - - case this.tok.T_STRING: - var current = [this.token, this.lexer.getState()]; - var label = this.text(); - // AST : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L457 - if (this.next().token === ':') { - var result = this.node('label'); - this.next(); - return result(label); - } - - // default fallback expr / T_STRING '::' (etc...) - this.lexer.tokens.push(current); - var expr = this.next().read_expr(); - this.expectEndOfStatement(); - return expr; - - case this.tok.T_GOTO: - var result = this.node('goto'), label = null; - if (this.next().expect(this.tok.T_STRING)) { - label = this.text(); - this.next().expectEndOfStatement(); - } - return result(label); - - default: // default fallback expr - var expr = this.read_expr(); - this.expectEndOfStatement(); - return expr; - } - } - /** - * ```ebnf - * code_block ::= '{' (inner_statements | top_statements) '}' - * ``` - */ - ,read_code_block: function(top) { - var result = this.node('block'); - this.expect('{') && this.nextWithComments(); - var body = top ? - this.read_top_statements() - : this.read_inner_statements() - ; - this.expect('}') && this.nextWithComments(); - return result(null, body); - } -}; - -},{}],112:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -module.exports = { - /** - * Reads a switch statement - * ```ebnf - * switch ::= T_SWITCH '(' expr ')' switch_case_list - * ``` - * @return {Switch} - * @see http://php.net/manual/en/control-structures.switch.php - */ - read_switch: function() { - this.expect(this.tok.T_SWITCH) && this.next(); - var result = this.node('switch'), test, body, shortForm; - this.expect('(') && this.next(); - test = this.read_expr(); - this.expect(')') && this.next(); - shortForm = (this.token === ':'); - body = this.read_switch_case_list(); - return result(test, body, shortForm); - } - /** - * ```ebnf - * switch_case_list ::= '{' ';'? case_list* '}' | ':' ';'? case_list* T_ENDSWITCH ';' - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L566 - */ - ,read_switch_case_list: function() { - // DETECT SWITCH MODE - var expect = null, - result = this.node('block'), - items = []; - if (this.token === '{') { - expect = '}'; - } else if (this.token === ':') { - expect = this.tok.T_ENDSWITCH; - } else { - this.expect(['{', ':']); - } - // OPTIONNAL ';' - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L570 - if (this.next().token === ';') { - this.next(); - } - // IGNORE THE CLOSE TAG TOKEN WITH SHORT MODE - if (this.token === this.tok.T_CLOSE_TAG) { - this.next(); - } - // EXTRACTING CASES - while(this.token !== this.EOF && this.token !== expect) { - items.push( this.read_case_list(expect) ); - } - // CHECK END TOKEN - this.expect(expect) && this.next(); - if (expect === this.tok.T_ENDSWITCH) { - this.expectEndOfStatement(); - } - return result(null, items); - } - /** - * ```ebnf - * case_list ::= ((T_CASE expr) | T_DEFAULT) (':' | ';') inner_statement* - * ``` - */ - ,read_case_list: function(stopToken) { - var result = this.node('case'), test = null, body = null, items = []; - if (this.token === this.tok.T_CASE) { - test = this.next().read_expr(); - } else if (this.token === this.tok.T_DEFAULT) { - // the defaut entry - no condition - this.next(); - } else { - this.expect([this.tok.T_CASE, this.tok.T_DEFAULT]); - } - this.expect([':', ';']) && this.next(); - body = this.node('block'); - while( - this.token != this.EOF - && this.token !== stopToken - && this.token !== this.tok.T_CASE - && this.token !== this.tok.T_DEFAULT - ) { - items.push(this.read_inner_statement()); - } - return result( - test, items.length > 0 ? body(null, items) : null - ); - } -}; - -},{}],113:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -module.exports = { - /** - * ```ebnf - * try ::= T_TRY '{' inner_statement* '}' - * ( - * T_CATCH '(' namespace_name variable ')' '{' inner_statement* '}' - * )* - * (T_FINALLY '{' inner_statement* '}')? - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L448 - * @return {Try} - */ - read_try: function() { - this.expect(this.tok.T_TRY); - var result = this.node('try'), - always = null, - body, - catches = [] - ; - body = this.next().read_statement(); - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L455 - while(this.ignoreComments().token === this.tok.T_CATCH) { - var item = this.node('catch'), what = [], variable = null; - this.next().expect('(') && this.next(); - what = this.read_list( - this.read_namespace_name, '|', false - ); - variable = this.read_variable(true, false, false); - this.expect(')'); - catches.push( - item(this.next().read_statement(), what, variable) - ); - } - if (this.token === this.tok.T_FINALLY) { - always = this.next().read_statement(); - } - return result(body, catches, always); - } -}; - -},{}],114:[function(require,module,exports){ -/*! - * Defines a list of helper functions for parsing - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -module.exports = { - /** - * Reads a short form of tokens - * @param {Number} token - The ending token - * @return {Block} - */ - read_short_form: function(token) { - var body = this.node('block'), items = []; - if (this.expect(':')) this.next(); - while(this.token != this.EOF && this.token !== token) { - items.push(this.read_inner_statement()); - } - if (this.expect(token)) this.next(); - this.expectEndOfStatement(); - return body(null, items); - } - - /** - * Helper : reads a list of tokens / sample : T_STRING ',' T_STRING ... - * ```ebnf - * list ::= separator? ( item separator )* item - * ``` - */ - ,read_list: function(item, separator, preserveFirstSeparator) { - var result = []; - - if (this.token == separator) { - if (preserveFirstSeparator) result.push(''); - this.next(); - } - - if (typeof (item) === "function") { - do { - result.push(item.apply(this, [])); - if (this.token != separator) { - break; - } - } while(this.next().token != this.EOF); - } else { - if (this.expect(item)) { - result.push(this.text()); - } else { - return []; - } - while (this.next().token != this.EOF) { - if (this.token != separator) break; - // trim current separator & check item - if (this.next().token != item) break; - result.push(this.text()); - } - } - return result; - } - - /** - * Reads a list of names separated by a comma - * - * ```ebnf - * name_list ::= namespace (',' namespace)* - * ``` - * - * Sample code : - * ```php - * func()->property // chained calls - * ``` - */ - read_variable: function(read_only, encapsed, byref) { - var result; - - // check the byref flag - if (!byref && this.token === '&') { - byref = true; - this.next(); - } - - // reads the entry point - if (this.is([this.tok.T_VARIABLE, '$'])) { - result = this.read_reference_variable(encapsed, byref); - } else if (this.is([this.tok.T_NS_SEPARATOR, this.tok.T_STRING, this.tok.T_NAMESPACE])) { - result = this.node(); - var name = this.read_namespace_name(); - if ( - this.token != this.tok.T_DOUBLE_COLON - && this.token != '(' - ) { - // @see parser.js line 130 : resolves a conflict with scalar - var literal = name.name.toLowerCase(); - if (literal === 'true') { - result = result('boolean', true); - } else if (literal === 'false') { - result = result('boolean', false); - } else { - // @todo null keyword ? - result = result('constref', name); - } - } else { - result = name; - } - } else if (this.token === this.tok.T_STATIC) { - result = this.node('constref'); - this.next(); - result = result('static'); - } else { - this.expect('VARIABLE'); - } - - // static mode - if (this.token === this.tok.T_DOUBLE_COLON) { - result = this.read_static_getter(result, encapsed); - } - - return this.recursive_variable_chain_scan(result, read_only, encapsed); - } - - // resolves a static call - ,read_static_getter: function(what, encapsed) { - var result = this.node('staticlookup'); - var offset = null; - if (this.next().is([this.tok.T_VARIABLE, '$'])) { - offset = this.read_reference_variable(encapsed, false); - } else if ( - this.token === this.tok.T_STRING - || this.token === this.tok.T_CLASS - ) { - offset = this.node('constref'); - var name = this.text(); - this.next(); - offset = offset(name); - } else { - this.error([this.tok.T_VARIABLE, this.tok.T_STRING]); - // graceful mode : set getter as error node and continue - offset = this.node('constref'); - var name = this.text(); - this.next(); - offset = offset(name); - } - return result(what, offset); - } - - ,recursive_variable_chain_scan: function(result, read_only, encapsed) { - recursive_scan_loop: - while(this.token != this.EOF) { - switch(this.token) { - case '(': - if (read_only) { - // @fixme : add more informations & test - return result; - } else { - result = this.node('call')( - result, this.read_function_argument_list() - ); - } - break; - case '[': - var node = this.node('offsetlookup'); - this.next(); - var offset = false; - if (encapsed) { - offset = this.read_encaps_var_offset(); - this.expect(']') && this.next(); - } else { - // callable_variable : https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L1122 - if (this.token !== ']') { - offset = this.read_expr(); - this.expect(']') && this.next(); - } else { - this.next(); - } - } - result = node(result, offset); - break; - case this.tok.T_OBJECT_OPERATOR: - var node = this.node('propertylookup'); - var what = null; - switch(this.next().token) { - case this.tok.T_STRING: - what = this.node('constref'); - var name = this.text(); - this.next(); - what = what(name); - if (this.token === this.tok.T_VARIABLE) { - var inner = this.node('variable'); - name = this.text().substring(1); - this.next(); - what = this.node('encapsed')( - [what, inner(name, false, false)], - 'offset' - ); - if (what.loc && what.value[0].loc) { - what.loc.start = what.value[0].loc.start; - } - } else if (this.token === '{') { - var expr = this.next().read_expr(); - this.expect('}') && this.next(); - what = this.node('encapsed')( - [what, expr], - 'offset' - ); - if (what.loc && what.value[0].loc) { - what.loc.start = what.value[0].loc.start; - } - } - break; - case this.tok.T_VARIABLE: - what = this.node('variable'); - var name = this.text().substring(1); - this.next(); - what = what(name, false, false); - break; - case '$': - this.next().expect(['{', this.tok.T_VARIABLE]); - if (this.token === '{') { - // $obj->${$varname} - what = this.next().read_expr(); - this.expect('}') && this.next(); - } else { - // $obj->$$varname - what = this.read_expr(); - } - break; - case '{': - what = this.next().read_expr(); - this.expect('}') && this.next(); - break; - default: - this.error([this.tok.T_STRING, this.tok.T_VARIABLE]); - // graceful mode : set what as error mode & continue - what = this.node('constref'); - var name = this.text(); - this.next(); - what = what(name); - break; - } - result = node(result, what); - break; - default: - break recursive_scan_loop; - } - } - return result; - } - /** - * https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L1231 - */ - ,read_encaps_var_offset: function() { - var offset = this.node(); - if (this.token === this.tok.T_STRING) { - var text = this.text(); - var isDblQuote = text[0] === '"'; - text = text.substring(1, text.length - 1); - this.next(); - offset = offset( - 'string', isDblQuote, this.resolve_special_chars(text) - ); - } else if (this.token === this.tok.T_NUM_STRING) { - var num = this.text(); - this.next(); - offset = offset('number', num); - } else if (this.token === this.tok.T_VARIABLE) { - var name = this.text().substring(1); - this.next(); - offset = offset('variable', name, false, false); - } else { - this.expect([ - this.tok.T_STRING, - this.tok.T_NUM_STRING, - this.tok.T_VARIABLE - ]); - // fallback : consider as text - var text = this.text(); - this.next(); - offset = offset('string', false, text); - } - return offset; - } - /** - * ```ebnf - * reference_variable ::= simple_variable ('[' OFFSET ']')* | '{' EXPR '}' - * ``` - * - * $foo[123]; // foo is an array ==> gets its entry - * $foo{1}; // foo is a string ==> get the 2nd char offset - * ${'foo'}[123]; // get the dynamic var $foo - * $foo[123]{1}; // gets the 2nd char from the 123 array entry - * - */ - ,read_reference_variable: function(encapsed, byref) { - var result = this.read_simple_variable(byref); - while(this.token != this.EOF) { - var node = this.node(); - if (this.token == '[') { - var offset = null; - if (encapsed) { - offset = this.next().read_encaps_var_offset(); - } else { - offset = this.next().token === ']' ? null : this.read_dim_offset(); - } - this.expect(']') && this.next(); - result = node('offsetlookup', result, offset); - } else if (this.token == '{' && !encapsed) { - var offset = this.next().read_expr(); - this.expect('}') && this.next(); - result = node('offsetlookup', result, offset); - } else break; - } - return result; - } - /** - * ```ebnf - * simple_variable ::= T_VARIABLE | '$' '{' expr '}' | '$' simple_variable - * ``` - */ - ,read_simple_variable: function(byref) { - var result = this.node('variable'); - if (this.expect([this.tok.T_VARIABLE, '$']) && this.token === this.tok.T_VARIABLE) { - // plain variable name - var name = this.text().substring(1); - this.next(); - result = result(name, byref, false); - } else { - if (this.token === '$') this.next(); - // dynamic variable name - switch(this.token) { - case '{': - var expr = this.next().read_expr(); - this.expect('}') && this.next(); - result = result(expr, byref, true); - break; - case '$': // $$$var - result = result(this.read_simple_variable(false), byref); - break; - case this.tok.T_VARIABLE: // $$var - var name = this.text().substring(1); - var node = this.node('variable'); - this.next(); - result = result(node(name, false, false), byref, false); - break; - default: - this.error(['{', '$', this.tok.T_VARIABLE]); - // graceful mode - var name = this.text(); - this.next(); - result = result(name, byref, false); - } - } - return result; - } -}; - -},{}],116:[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -// exports token index -module.exports = { - values: { - 101: 'T_HALT_COMPILER', - 102: 'T_USE', - 103: 'T_ENCAPSED_AND_WHITESPACE', - 104: 'T_OBJECT_OPERATOR', - 105: 'T_STRING', - 106: 'T_DOLLAR_OPEN_CURLY_BRACES', - 107: 'T_STRING_VARNAME', - 108: 'T_CURLY_OPEN', - 109: 'T_NUM_STRING', - 110: 'T_ISSET', - 111: 'T_EMPTY', - 112: 'T_INCLUDE', - 113: 'T_INCLUDE_ONCE', - 114: 'T_EVAL', - 115: 'T_REQUIRE', - 116: 'T_REQUIRE_ONCE', - 117: 'T_NAMESPACE', - 118: 'T_NS_SEPARATOR', - 119: 'T_AS', - 120: 'T_IF', - 121: 'T_ENDIF', - 122: 'T_WHILE', - 123: 'T_DO', - 124: 'T_FOR', - 125: 'T_SWITCH', - 126: 'T_BREAK', - 127: 'T_CONTINUE', - 128: 'T_RETURN', - 129: 'T_GLOBAL', - 130: 'T_STATIC', - 131: 'T_ECHO', - 132: 'T_INLINE_HTML', - 133: 'T_UNSET', - 134: 'T_FOREACH', - 135: 'T_DECLARE', - 136: 'T_TRY', - 137: 'T_THROW', - 138: 'T_GOTO', - 139: 'T_FINALLY', - 140: 'T_CATCH', - 141: 'T_ENDDECLARE', - 142: 'T_LIST', - 143: 'T_CLONE', - 144: 'T_PLUS_EQUAL', - 145: 'T_MINUS_EQUAL', - 146: 'T_MUL_EQUAL', - 147: 'T_DIV_EQUAL', - 148: 'T_CONCAT_EQUAL', - 149: 'T_MOD_EQUAL', - 150: 'T_AND_EQUAL', - 151: 'T_OR_EQUAL', - 152: 'T_XOR_EQUAL', - 153: 'T_SL_EQUAL', - 154: 'T_SR_EQUAL', - 155: 'T_INC', - 156: 'T_DEC', - 157: 'T_BOOLEAN_OR', - 158: 'T_BOOLEAN_AND', - 159: 'T_LOGICAL_OR', - 160: 'T_LOGICAL_AND', - 161: 'T_LOGICAL_XOR', - 162: 'T_SL', - 163: 'T_SR', - 164: 'T_IS_IDENTICAL', - 165: 'T_IS_NOT_IDENTICAL', - 166: 'T_IS_EQUAL', - 167: 'T_IS_NOT_EQUAL', - 168: 'T_IS_SMALLER_OR_EQUAL', - 169: 'T_IS_GREATER_OR_EQUAL', - 170: 'T_INSTANCEOF', - 171: 'T_INT_CAST', - 172: 'T_DOUBLE_CAST', - 173: 'T_STRING_CAST', - 174: 'T_ARRAY_CAST', - 175: 'T_OBJECT_CAST', - 176: 'T_BOOL_CAST', - 177: 'T_UNSET_CAST', - 178: 'T_EXIT', - 179: 'T_PRINT', - 180: 'T_YIELD', - 181: 'T_YIELD_FROM', - 182: 'T_FUNCTION', - 183: 'T_DOUBLE_ARROW', - 184: 'T_DOUBLE_COLON', - 185: 'T_ARRAY', - 186: 'T_CALLABLE', - 187: 'T_CLASS', - 188: 'T_ABSTRACT', - 189: 'T_TRAIT', - 190: 'T_FINAL', - 191: 'T_EXTENDS', - 192: 'T_INTERFACE', - 193: 'T_IMPLEMENTS', - 194: 'T_VAR', - 195: 'T_PUBLIC', - 196: 'T_PROTECTED', - 197: 'T_PRIVATE', - 198: 'T_CONST', - 199: 'T_NEW', - 200: 'T_INSTEADOF', - 201: 'T_ELSEIF', - 202: 'T_ELSE', - 203: 'T_ENDSWITCH', - 204: 'T_CASE', - 205: 'T_DEFAULT', - 206: 'T_ENDFOR', - 207: 'T_ENDFOREACH', - 208: 'T_ENDWHILE', - 209: 'T_CONSTANT_ENCAPSED_STRING', - 210: 'T_LNUMBER', - 211: 'T_DNUMBER', - 212: 'T_LINE', - 213: 'T_FILE', - 214: 'T_DIR', - 215: 'T_TRAIT_C', - 216: 'T_METHOD_C', - 217: 'T_FUNC_C', - 218: 'T_NS_C', - 219: 'T_START_HEREDOC', - 220: 'T_END_HEREDOC', - 221: 'T_CLASS_C', - 222: 'T_VARIABLE', - 223: 'T_OPEN_TAG', - 224: 'T_OPEN_TAG_WITH_ECHO', - 225: 'T_CLOSE_TAG', - 226: 'T_WHITESPACE', - 227: 'T_COMMENT', - 228: 'T_DOC_COMMENT', - 229: 'T_ELLIPSIS', - 230: 'T_COALESCE', - 231: 'T_POW', - 232: 'T_POW_EQUAL', - 233: 'T_SPACESHIP' - }, - names: { - T_HALT_COMPILER: 101, - T_USE: 102, - T_ENCAPSED_AND_WHITESPACE: 103, - T_OBJECT_OPERATOR: 104, - T_STRING: 105, - T_DOLLAR_OPEN_CURLY_BRACES: 106, - T_STRING_VARNAME: 107, - T_CURLY_OPEN: 108, - T_NUM_STRING: 109, - T_ISSET: 110, - T_EMPTY: 111, - T_INCLUDE: 112, - T_INCLUDE_ONCE: 113, - T_EVAL: 114, - T_REQUIRE: 115, - T_REQUIRE_ONCE: 116, - T_NAMESPACE: 117, - T_NS_SEPARATOR: 118, - T_AS: 119, - T_IF: 120, - T_ENDIF: 121, - T_WHILE: 122, - T_DO: 123, - T_FOR: 124, - T_SWITCH: 125, - T_BREAK: 126, - T_CONTINUE: 127, - T_RETURN: 128, - T_GLOBAL: 129, - T_STATIC: 130, - T_ECHO: 131, - T_INLINE_HTML: 132, - T_UNSET: 133, - T_FOREACH: 134, - T_DECLARE: 135, - T_TRY: 136, - T_THROW: 137, - T_GOTO: 138, - T_FINALLY: 139, - T_CATCH: 140, - T_ENDDECLARE: 141, - T_LIST: 142, - T_CLONE: 143, - T_PLUS_EQUAL: 144, - T_MINUS_EQUAL: 145, - T_MUL_EQUAL: 146, - T_DIV_EQUAL: 147, - T_CONCAT_EQUAL: 148, - T_MOD_EQUAL: 149, - T_AND_EQUAL: 150, - T_OR_EQUAL: 151, - T_XOR_EQUAL: 152, - T_SL_EQUAL: 153, - T_SR_EQUAL: 154, - T_INC: 155, - T_DEC: 156, - T_BOOLEAN_OR: 157, - T_BOOLEAN_AND: 158, - T_LOGICAL_OR: 159, - T_LOGICAL_AND: 160, - T_LOGICAL_XOR: 161, - T_SL: 162, - T_SR: 163, - T_IS_IDENTICAL: 164, - T_IS_NOT_IDENTICAL: 165, - T_IS_EQUAL: 166, - T_IS_NOT_EQUAL: 167, - T_IS_SMALLER_OR_EQUAL: 168, - T_IS_GREATER_OR_EQUAL: 169, - T_INSTANCEOF: 170, - T_INT_CAST: 171, - T_DOUBLE_CAST: 172, - T_STRING_CAST: 173, - T_ARRAY_CAST: 174, - T_OBJECT_CAST: 175, - T_BOOL_CAST: 176, - T_UNSET_CAST: 177, - T_EXIT: 178, - T_PRINT: 179, - T_YIELD: 180, - T_YIELD_FROM: 181, - T_FUNCTION: 182, - T_DOUBLE_ARROW: 183, - T_DOUBLE_COLON: 184, - T_ARRAY: 185, - T_CALLABLE: 186, - T_CLASS: 187, - T_ABSTRACT: 188, - T_TRAIT: 189, - T_FINAL: 190, - T_EXTENDS: 191, - T_INTERFACE: 192, - T_IMPLEMENTS: 193, - T_VAR: 194, - T_PUBLIC: 195, - T_PROTECTED: 196, - T_PRIVATE: 197, - T_CONST: 198, - T_NEW: 199, - T_INSTEADOF: 200, - T_ELSEIF: 201, - T_ELSE: 202, - T_ENDSWITCH: 203, - T_CASE: 204, - T_DEFAULT: 205, - T_ENDFOR: 206, - T_ENDFOREACH: 207, - T_ENDWHILE: 208, - T_CONSTANT_ENCAPSED_STRING: 209, - T_LNUMBER: 210, - T_DNUMBER: 211, - T_LINE: 212, - T_FILE: 213, - T_DIR: 214, - T_TRAIT_C: 215, - T_METHOD_C: 216, - T_FUNC_C: 217, - T_NS_C: 218, - T_START_HEREDOC: 219, - T_END_HEREDOC: 220, - T_CLASS_C: 221, - T_VARIABLE: 222, - T_OPEN_TAG: 223, - T_OPEN_TAG_WITH_ECHO: 224, - T_CLOSE_TAG: 225, - T_WHITESPACE: 226, - T_COMMENT: 227, - T_DOC_COMMENT: 228, - T_ELLIPSIS: 229, - T_COALESCE: 230, - T_POW: 231, - T_POW_EQUAL: 232, - T_SPACESHIP: 233 - } -}; - -},{}],"php-parser":[function(require,module,exports){ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var lexer = require('./lexer'); -var parser = require('./parser'); -var tokens = require('./tokens'); -var AST = require('./ast'); - -/** - * @private combine structures - */ -function combine(src, to) { - var keys = Object.keys(src); - var i = keys.length; - while (i--) { - var k = keys[i]; - var val = src[k]; - if (val === null) { - delete to[k]; - } else if (typeof val === 'function') { - to[k] = val.bind(to); - } else if (Array.isArray(val)) { - to[k] = Array.isArray(to[k]) ? to[k].concat(val) : val; - } else if (typeof val === 'object') { - to[k] = typeof to[k] === 'object' ? combine(val, to[k]) : val; - } else { - to[k] = val; - } - } - return to; -} - -/** - * Initialise a new parser instance with the specified options - * - * Usage : - * ```js - * var parser = require('php-parser'); - * var instance = new parser({ - * parser: { - * extractDoc: true, - * suppressErrors: true - * }, - * ast: { - * withPositions: true - * }, - * lexer: { - * short_tags: true, - * asp_tags: true - * } - * }); - * - * var evalAST = instance.parseEval('some php code'); - * var codeAST = instance.parseCode(' Note that the output tokens are *STRICLY* similar to PHP function `token_get_all` - * @param {String} buffer - * @return {String[]} - Each item can be a string or an array with following informations [token_name, text, line_number] - */ -engine.prototype.tokenGetAll = function(buffer) { - this.lexer.mode_eval = false; - this.lexer.all_tokens = true; - var EOF = this.lexer.EOF; - var names = this.tokens.values; - this.lexer.setInput(buffer); - var token = this.lexer.lex() || EOF; - var result = []; - while(token != EOF) { - var entry = this.lexer.yytext; - if (names.hasOwnProperty(token)) { - entry = [names[token], entry, this.lexer.yylloc.first_line]; - } - result.push(entry); - token = this.lexer.lex() || EOF; - } - return result; -}; - -// exports the function -module.exports = engine; - -},{"./ast":2,"./lexer":91,"./parser":100,"./tokens":116}]},{},[]); diff --git a/dist/php-parser.min.js b/dist/php-parser.min.js deleted file mode 100644 index 582bccd59..000000000 --- a/dist/php-parser.min.js +++ /dev/null @@ -1,114 +0,0 @@ -require=function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o1)for(var i=1;i"],["<","<=",">",">="],["<<",">>"],["+","-","."],["*","/","%"],["!"],["instanceof"]].forEach(function(list,index){list.forEach(function(operator){AST.precedence[operator]=index+1})});AST.prototype.resolvePrecedence=function(result){var buffer;if("bin"===result.kind){if(result.right)if("bin"===result.right.kind){var lLevel=AST.precedence[result.type],rLevel=AST.precedence[result.right.type];lLevel&&rLevel&&rLevel<=lLevel&&(buffer=result.right,result.right=result.right.left,buffer.left=this.resolvePrecedence(result),result=buffer); -}else if("retif"===result.right.kind){var lLevel=AST.precedence[result.type],rLevel=AST.precedence["?"];lLevel&&rLevel&&rLevel<=lLevel&&(buffer=result.right,result.right=result.right.test,buffer.test=this.resolvePrecedence(result),result=buffer)}}else if("unary"===result.kind)result.what&&("bin"===result.what.kind?(buffer=result.what,result.what=result.what.left,buffer.left=this.resolvePrecedence(result),result=buffer):"retif"===result.what.kind&&(buffer=result.what,result.what=result.what.test,buffer.test=this.resolvePrecedence(result),result=buffer));else if("retif"===result.kind)result.falseExpr&&"retif"===result.falseExpr.kind&&(buffer=result.falseExpr,result.falseExpr=buffer.test,buffer.test=this.resolvePrecedence(result),result=buffer);else if("assign"===result.kind&&result.right&&"bin"===result.right.kind){var lLevel=AST.precedence["="],rLevel=AST.precedence[result.right.type];lLevel&&rLevel&&rLevel=this.size,!this.all_tokens&&this.mode_eval?this.begin("ST_IN_SCRIPTING"):this.begin("INITIAL"),this},lexer.prototype.input=function(size){var ch=this._input[this.offset]; -return ch?(this.yytext+=ch,this.offset++,"\r"===ch&&"\n"===this._input[this.offset]&&(this.yytext+="\n",this.offset++),"\n"===ch||"\r"===ch?(this.yylloc.last_line=++this.yylineno,this.yyprevcol=this.yylloc.last_column,this.yylloc.last_column=0):this.yylloc.last_column++,ch):""},lexer.prototype.unput=function(size){if(1===size)this.offset--,"\n"===this._input[this.offset]&&"\r"===this._input[this.offset-1]&&(this.offset--,size++),"\r"===this._input[this.offset]||"\n"===this._input[this.offset]?(this.yylloc.last_line--,this.yylineno--,this.yylloc.last_column=this.yyprevcol):this.yylloc.last_column--,this.yytext=this.yytext.substring(0,this.yytext.length-size);else if(size>0)if(this.offset-=size,size0?this.conditionStack.pop():this.conditionStack[0];if(this.curCondition=this.conditionStack[this.conditionStack.length-1],this.stateCb=this["match"+this.curCondition],"function"!=typeof this.stateCb)throw new Error('Undefined condition state "'+this.curCondition+'"');return condition},lexer.prototype.next=function(){var token;if(this._input||(this.done=!0),this.yylloc.first_offset=this.offset,this.yylloc.first_line=this.yylloc.last_line, -this.yylloc.first_column=this.yylloc.last_column,this.yytext="",this.done)return this.yylloc.prev_offset=this.yylloc.first_offset,this.yylloc.prev_line=this.yylloc.first_line,this.yylloc.prev_column=this.yylloc.first_column,this.EOF;if(this.tokens.length>0?(token=this.tokens.shift(),"object"==typeof token[1]?this.setState(token[1]):this.consume(token[1]),token=token[0]):token=this.stateCb.apply(this,[]),this.offset>=this.size&&0===this.tokens.length&&(this.done=!0),this.debug){var tName=token;tName="number"==typeof tName?this.engine.tokens.values[tName]:'"'+tName+'"';var e=new Error(tName+"\tfrom "+this.yylloc.first_line+","+this.yylloc.first_column+"\t - to "+this.yylloc.last_line+","+this.yylloc.last_column+'\t"'+this.yytext+'"');console.log(e.stack)}return token},[require("./lexer/comments.js"),require("./lexer/initial.js"),require("./lexer/numbers.js"),require("./lexer/property.js"),require("./lexer/scripting.js"),require("./lexer/strings.js"),require("./lexer/tokens.js"),require("./lexer/utils.js")].forEach(function(ext){ -for(var k in ext)lexer.prototype[k]=ext[k]}),module.exports=lexer},{"./lexer/comments.js":92,"./lexer/initial.js":93,"./lexer/numbers.js":94,"./lexer/property.js":95,"./lexer/scripting.js":96,"./lexer/strings.js":97,"./lexer/tokens.js":98,"./lexer/utils.js":99}],92:[function(require,module,exports){"use strict";module.exports={T_COMMENT:function(){for(;this.offset"===this._input[this.offset])return this.unput(1),this.tok.T_COMMENT;if("%"===ch&&this.aspTagMode&&">"===this._input[this.offset])return this.unput(1),this.tok.T_COMMENT}return this.tok.T_COMMENT},T_DOC_COMMENT:function(){var ch=this.input(),token=this.tok.T_COMMENT;if("*"===ch){if(ch=this.input(),this.is_WHITESPACE()&&(token=this.tok.T_DOC_COMMENT),"/"===ch)return token;this.unput(1)}for(;this.offset1&&"INITIAL"===this.conditionStack[this.conditionStack.length-1]?this.popState():this.begin("ST_IN_SCRIPTING"),this},matchINITIAL:function(){for(;this.offset0&&this.tok.T_INLINE_HTML}}},{}],94:[function(require,module,exports){(function(process){ -"use strict";if("x64"==process.arch)var MAX_LENGTH_OF_LONG=19,long_min_digits="9223372036854775808";else var MAX_LENGTH_OF_LONG=10,long_min_digits="2147483648";module.exports={consume_NUM:function(){var ch=this.yytext[0],hasPoint="."===this.yytext[0];if("0"===ch)if(ch=this.input(),"x"===ch||"X"===ch){if(this.input(),this.is_HEX())return this.consume_HNUM();this.unput(2)}else if("b"===ch||"B"===ch){if(ch=this.input(),"0"===ch||"1"===ch)return this.consume_BNUM();this.unput(2)}else this.is_NUM()||this.unput(1);for(;this.offset"===ch)return this.tok.T_OBJECT_OPERATOR;ch&&this.unput(1)}else if(this.is_LABEL_START())return this.consume_LABEL(),this.popState(),this.tok.T_STRING;return this.popState(),ch&&this.unput(1),!1},matchST_LOOKING_FOR_VARNAME:function(){var ch=this.input();return this.is_LABEL_START()?(this.consume_LABEL(),ch=this.input(),this.popState(),"["===ch||"}"===ch?(this.begin("ST_IN_SCRIPTING"),this.unput(1),this.tok.T_STRING_VARNAME):(this.unput(this.yytext.length), -!1)):(ch&&this.unput(1),this.popState(),this.begin("ST_IN_SCRIPTING"),!1)},matchST_VAR_OFFSET:function(){var ch=this.input();if(this.is_NUM())return this.consume_NUM(),this.tok.T_NUM_STRING;if("]"===ch)return this.popState(),"]";if("$"===ch){if(this.input(),this.is_LABEL_START())return this.consume_LABEL(),this.tok.T_VARIABLE;throw new Error("Unexpected terminal")}if(this.is_LABEL_START())return this.consume_LABEL(),this.tok.T_STRING;if(this.is_WHITESPACE()||"\\"===ch||"'"===ch||"#"===ch)return this.tok.T_ENCAPSED_AND_WHITESPACE;if("["===ch||"{"===ch||"}"===ch||'"'===ch||"`"===ch||this.is_TOKEN())return ch;throw new Error("Unexpected terminal")}}},{}],96:[function(require,module,exports){module.exports={matchST_IN_SCRIPTING:function(){var ch=this.input();switch(ch){case" ":case"\t":case"\n":case"\r":case"\r\n":return this.T_WHITESPACE();case"#":return this.T_COMMENT();case"/":return"/"===this._input[this.offset]?this.T_COMMENT():"*"===this._input[this.offset]?(this.input(),this.T_DOC_COMMENT()):this.consume_TOKEN(); -case"'":return this.T_CONSTANT_ENCAPSED_STRING();case'"':return this.ST_DOUBLE_QUOTES();case"`":return this.begin("ST_BACKQUOTE"),"`";case"?":if(!this.aspTagMode&&this.tryMatch(">")){this.input();var nextCH=this._input[this.offset];return"\n"!==nextCH&&"\r"!==nextCH||this.input(),this.conditionStack.length>1&&this.begin("INITIAL"),this.tok.T_CLOSE_TAG}return this.consume_TOKEN();case"%":return this.aspTagMode&&">"===this._input[this.offset]?(this.input(),ch=this._input[this.offset],"\n"!==ch&&"\r"!==ch||this.input(),this.aspTagMode=!1,this.conditionStack.length>1&&this.begin("INITIAL"),this.tok.T_CLOSE_TAG):this.consume_TOKEN();case"{":return this.begin("ST_IN_SCRIPTING"),"{";case"}":return this.conditionStack.length>2&&this.popState(),"}";default:if("."===ch){if(ch=this.input(),this.is_NUM())return this.consume_NUM();ch&&this.unput(1)}if(this.is_NUM())return this.consume_NUM();if(this.is_LABEL_START())return this.consume_LABEL().T_STRING();if(this.is_TOKEN())return this.consume_TOKEN()}throw new Error('Bad terminal sequence "'+ch+'" at line '+this.yylineno+" (offset "+this.offset+")"); -},T_WHITESPACE:function(){for(;this.offset2&&this.appendToken(this.tok.T_ENCAPSED_AND_WHITESPACE,this.yytext.length-prefix),this.unput(this.yytext.length-prefix),this.begin("ST_DOUBLE_QUOTES"),this.yytext},isDOC_MATCH:function(){if(this._input.substring(this.offset-1,this.offset-1+this.heredoc_label.length)===this.heredoc_label){var ch=this._input[this.offset-1+this.heredoc_label.length];if("\n"===ch||"\r"===ch||";"===ch)return!0; -}return!1},matchST_NOWDOC:function(){if(this.isDOC_MATCH())return this.consume(this.heredoc_label.length),this.popState(),this.tok.T_END_HEREDOC;for(var ch=this._input[this.offset-1];this.offset2?(this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES,2), -this.unput(2),this.tok.T_ENCAPSED_AND_WHITESPACE):this.tok.T_DOLLAR_OPEN_CURLY_BRACES;if(this.is_LABEL_START()){var yyoffset=this.offset,next=this.consume_VARIABLE();return this.yytext.length>this.offset-yyoffset+2?(this.appendToken(next,this.offset-yyoffset+2),this.unput(this.offset-yyoffset+2),this.tok.T_ENCAPSED_AND_WHITESPACE):next}}else if("{"===ch){if(ch=this.input(),"$"===ch)return this.begin("ST_IN_SCRIPTING"),this.yytext.length>2?(this.appendToken(this.tok.T_CURLY_OPEN,1),this.unput(2),this.tok.T_ENCAPSED_AND_WHITESPACE):(this.unput(1),this.tok.T_CURLY_OPEN)}else ch=this.input();return this.tok.T_ENCAPSED_AND_WHITESPACE},consume_VARIABLE:function(){if(this.consume_LABEL(),ch=this.input(),"["==ch)return this.unput(1),this.begin("ST_VAR_OFFSET"),this.tok.T_VARIABLE;if("-"===ch){if(">"===this.input())return this.input(),this.is_LABEL_START()&&this.begin("ST_LOOKING_FOR_PROPERTY"),this.unput(3),this.tok.T_VARIABLE;this.unput(2)}else this.unput(1);return this.tok.T_VARIABLE},matchST_BACKQUOTE:function(){var ch=this.input(); -if("$"===ch){if(ch=this.input(),"{"===ch)return this.begin("ST_LOOKING_FOR_VARNAME"),this.tok.T_DOLLAR_OPEN_CURLY_BRACES;if(this.is_LABEL_START()){var tok=this.consume_VARIABLE();return tok}}else if("{"===ch){if("$"===this._input[this.offset])return this.begin("ST_IN_SCRIPTING"),this.tok.T_CURLY_OPEN}else if("`"===ch)return this.popState(),"`";for(;this.offset2?(this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES,2),this.unput(2),this.tok.T_ENCAPSED_AND_WHITESPACE):this.tok.T_DOLLAR_OPEN_CURLY_BRACES;if(this.is_LABEL_START()){var yyoffset=this.offset,next=this.consume_VARIABLE();return this.yytext.length>this.offset-yyoffset+2?(this.appendToken(next,this.offset-yyoffset+2),this.unput(this.offset-yyoffset+2),this.tok.T_ENCAPSED_AND_WHITESPACE):next}this.unput(1)}else if("{"===ch){if(ch=this.input(), -"$"===ch)return this.begin("ST_IN_SCRIPTING"),this.yytext.length>2?(this.appendToken(this.tok.T_CURLY_OPEN,1),this.unput(2),this.tok.T_ENCAPSED_AND_WHITESPACE):(this.unput(1),this.tok.T_CURLY_OPEN);this.unput(1)}}ch=this.input()}return this.tok.T_ENCAPSED_AND_WHITESPACE},matchST_DOUBLE_QUOTES:function(){var ch=this.input();if("$"===ch){if(ch=this.input(),"{"===ch)return this.begin("ST_LOOKING_FOR_VARNAME"),this.tok.T_DOLLAR_OPEN_CURLY_BRACES;if(this.is_LABEL_START()){var tok=this.consume_VARIABLE();return tok}}else if("{"===ch){if("$"===this._input[this.offset])return this.begin("ST_IN_SCRIPTING"),this.tok.T_CURLY_OPEN}else if('"'===ch)return this.popState(),'"';for(;this.offset2?(this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES,2),this.unput(2),this.tok.T_ENCAPSED_AND_WHITESPACE):this.tok.T_DOLLAR_OPEN_CURLY_BRACES; -if(this.is_LABEL_START()){var yyoffset=this.offset,next=this.consume_VARIABLE();return this.yytext.length>this.offset-yyoffset+2?(this.appendToken(next,this.offset-yyoffset+2),this.unput(this.offset-yyoffset+2),this.tok.T_ENCAPSED_AND_WHITESPACE):next}this.unput(1)}else if("{"===ch){if(ch=this.input(),"$"===ch)return this.begin("ST_IN_SCRIPTING"),this.yytext.length>2?(this.appendToken(this.tok.T_CURLY_OPEN,1),this.unput(2),this.tok.T_ENCAPSED_AND_WHITESPACE):(this.unput(1),this.tok.T_CURLY_OPEN);ch&&this.unput(1)}}ch=this.input()}return this.tok.T_ENCAPSED_AND_WHITESPACE}}},{}],98:[function(require,module,exports){module.exports={T_STRING:function(){var token=this.yytext.toLowerCase(),id=this.keywords[token];if(!id)if("yield"===token)this.tryMatch(" from")?(this.consume(5),id=this.tok.T_YIELD_FROM):id=this.tok.T_YIELD;else if(id=this.tok.T_STRING,"b"===token||"B"===token){var ch=this.input(1);if('"'===ch)return this.ST_DOUBLE_QUOTES();if("'"===ch)return this.T_CONSTANT_ENCAPSED_STRING();ch&&this.unput(1)}return id; -},consume_TOKEN:function(){var ch=this._input[this.offset-1],fn=this.tokenTerminals[ch];return fn?fn.apply(this,[]):this.yytext},tokenTerminals:{$:function(){return this.offset++,this.is_LABEL_START()?(this.offset--,this.consume_LABEL(),this.tok.T_VARIABLE):(this.offset--,"$")},"-":function(){var nchar=this._input[this.offset];return">"===nchar?(this.begin("ST_LOOKING_FOR_PROPERTY").input(),this.tok.T_OBJECT_OPERATOR):"-"===nchar?(this.input(),this.tok.T_DEC):"="===nchar?(this.input(),this.tok.T_MINUS_EQUAL):"-"},"\\":function(){return this.tok.T_NS_SEPARATOR},"/":function(){return"="===this._input[this.offset]?(this.input(),this.tok.T_DIV_EQUAL):"/"},":":function(){return":"===this._input[this.offset]?(this.input(),this.tok.T_DOUBLE_COLON):":"},"(":function(){var initial=this.offset;if(this.input(),this.is_TABSPACE()&&this.consume_TABSPACE().input(),this.is_LABEL_START()){var yylen=this.yytext.length;this.consume_LABEL();var castToken=this.yytext.substring(yylen-1).toLowerCase(),castId=this.castKeywords[castToken]; -if(castId&&(this.input(),this.is_TABSPACE()&&this.consume_TABSPACE().input(),")"===this._input[this.offset-1]))return castId}return this.unput(this.offset-initial),"("},"=":function(){var nchar=this._input[this.offset];return">"===nchar?(this.input(),this.tok.T_DOUBLE_ARROW):"="===nchar?"="===this._input[this.offset+1]?(this.consume(2),this.tok.T_IS_IDENTICAL):(this.input(),this.tok.T_IS_EQUAL):"="},"+":function(){var nchar=this._input[this.offset];return"+"===nchar?(this.input(),this.tok.T_INC):"="===nchar?(this.input(),this.tok.T_PLUS_EQUAL):"+"},"!":function(){return"="===this._input[this.offset]?"="===this._input[this.offset+1]?(this.consume(2),this.tok.T_IS_NOT_IDENTICAL):(this.input(),this.tok.T_IS_NOT_EQUAL):"!"},"?":function(){return"?"===this._input[this.offset]?(this.input(),this.tok.T_COALESCE):"?"},"<":function(){var nchar=this._input[this.offset];return"<"===nchar?(nchar=this._input[this.offset+1],"="===nchar?(this.consume(2),this.tok.T_SL_EQUAL):"<"===nchar&&this.is_HEREDOC()?this.tok.T_START_HEREDOC:(this.input(), -this.tok.T_SL)):"="===nchar?(this.input(),">"===this._input[this.offset]?(this.input(),this.tok.T_SPACESHIP):this.tok.T_IS_SMALLER_OR_EQUAL):">"===nchar?(this.input(),this.tok.T_IS_NOT_EQUAL):"<"},">":function(){var nchar=this._input[this.offset];return"="===nchar?(this.input(),this.tok.T_IS_GREATER_OR_EQUAL):">"===nchar?(nchar=this._input[this.offset+1],"="===nchar?(this.consume(2),this.tok.T_SR_EQUAL):(this.input(),this.tok.T_SR)):">"},"*":function(){var nchar=this._input[this.offset];return"="===nchar?(this.input(),this.tok.T_MUL_EQUAL):"*"===nchar?(this.input(),"="===this._input[this.offset]?(this.input(),this.tok.T_POW_EQUAL):this.tok.T_POW):"*"},".":function(){var nchar=this._input[this.offset];return"="===nchar?(this.input(),this.tok.T_CONCAT_EQUAL):"."===nchar&&"."===this._input[this.offset+1]?(this.consume(2),this.tok.T_ELLIPSIS):"."},"%":function(){return"="===this._input[this.offset]?(this.input(),this.tok.T_MOD_EQUAL):"%"},"&":function(){var nchar=this._input[this.offset];return"="===nchar?(this.input(), -this.tok.T_AND_EQUAL):"&"===nchar?(this.input(),this.tok.T_BOOLEAN_AND):"&"},"|":function(){var nchar=this._input[this.offset];return"="===nchar?(this.input(),this.tok.T_OR_EQUAL):"|"===nchar?(this.input(),this.tok.T_BOOLEAN_OR):"|"},"^":function(){return"="===this._input[this.offset]?(this.input(),this.tok.T_XOR_EQUAL):"^"}}}},{}],99:[function(require,module,exports){var tokens=";:,.\\[]()|^&+-/*=%!~$<>?@";module.exports={is_NUM:function(){var ch=this._input.charCodeAt(this.offset-1);return ch>47&&ch<58},is_LABEL:function(){var ch=this._input.charCodeAt(this.offset-1);return ch>96&&ch<123||ch>64&&ch<91||95===ch||ch>47&&ch<58||ch>126},is_LABEL_START:function(){var ch=this._input.charCodeAt(this.offset-1);return ch>96&&ch<123||ch>64&&ch<91||95===ch||ch>126},consume_LABEL:function(){for(;this.offset47&&ch<58||ch>64&&ch<71||ch>96&&ch<103}}},{}],100:[function(require,module,exports){function isNumber(n){return"."!=n&&","!=n&&!isNaN(parseFloat(n))&&isFinite(n)}var parser=function(lexer,ast){this.lexer=lexer,this.ast=ast,this.tok=lexer.tok,this.EOF=lexer.EOF,this.token=null,this.prev=null,this.debug=!1,this.extractDoc=!1,this.suppressErrors=!1,this.entries={VARIABLE:[this.tok.T_VARIABLE,"$","&",this.tok.T_NS_SEPARATOR,this.tok.T_STRING,this.tok.T_NAMESPACE,this.tok.T_STATIC],SCALAR:[this.tok.T_CONSTANT_ENCAPSED_STRING,this.tok.T_START_HEREDOC,this.tok.T_LNUMBER,this.tok.T_DNUMBER,this.tok.T_ARRAY,"[",this.tok.T_CLASS_C,this.tok.T_TRAIT_C,this.tok.T_FUNC_C,this.tok.T_METHOD_C,this.tok.T_LINE,this.tok.T_FILE,this.tok.T_DIR,this.tok.T_NS_C,'"','b"','B"',"-",this.tok.T_NS_SEPARATOR], -T_MAGIC_CONST:[this.tok.T_CLASS_C,this.tok.T_TRAIT_C,this.tok.T_FUNC_C,this.tok.T_METHOD_C,this.tok.T_LINE,this.tok.T_FILE,this.tok.T_DIR,this.tok.T_NS_C],T_MEMBER_FLAGS:[this.tok.T_PUBLIC,this.tok.T_PRIVATE,this.tok.T_PROTECTED,this.tok.T_STATIC,this.tok.T_ABSTRACT,this.tok.T_FINAL],EOS:[";",this.tok.T_CLOSE_TAG,this.EOF,this.tok.T_INLINE_HTML],EXPR:["@","-","+","!","~","(","`",this.tok.T_LIST,this.tok.T_CLONE,this.tok.T_INC,this.tok.T_DEC,this.tok.T_NEW,this.tok.T_ISSET,this.tok.T_EMPTY,this.tok.T_INCLUDE,this.tok.T_INCLUDE_ONCE,this.tok.T_REQUIRE,this.tok.T_REQUIRE_ONCE,this.tok.T_EVAL,this.tok.T_INT_CAST,this.tok.T_DOUBLE_CAST,this.tok.T_STRING_CAST,this.tok.T_ARRAY_CAST,this.tok.T_OBJECT_CAST,this.tok.T_BOOL_CAST,this.tok.T_UNSET_CAST,this.tok.T_EXIT,this.tok.T_PRINT,this.tok.T_YIELD,this.tok.T_STATIC,this.tok.T_FUNCTION,this.tok.T_VARIABLE,"$",this.tok.T_NS_SEPARATOR,this.tok.T_STRING,this.tok.T_STRING,this.tok.T_CONSTANT_ENCAPSED_STRING,this.tok.T_START_HEREDOC,this.tok.T_LNUMBER,this.tok.T_DNUMBER,this.tok.T_ARRAY,"[",this.tok.T_CLASS_C,this.tok.T_TRAIT_C,this.tok.T_FUNC_C,this.tok.T_METHOD_C,this.tok.T_LINE,this.tok.T_FILE,this.tok.T_DIR,this.tok.T_NS_C] -}};parser.prototype.getTokenName=function(token){return isNumber(token)?token==this.EOF?"the end of file (EOF)":this.lexer.engine.tokens.values[token]:"'"+token+"'"},parser.prototype.parse=function(code,filename){this._errors=[],this.filename=filename||"eval",this.currentNamespace=[""],this.lexer.setInput(code),this.lexer.comment_tokens=this.extractDoc,this.length=this.lexer._input.length,this.innerList=!1;var program=this.ast.prepare("program",this),childs=[];for(this.nextWithComments();this.token!=this.EOF;){var node=this.read_start();null!==node&&void 0!==node&&(Array.isArray(node)?childs=childs.concat(node):childs.push(node))}return program(childs,this._errors)},parser.prototype.raiseError=function(message,msgExpect,expect,token){if(message+=" on line "+this.lexer.yylloc.first_line,!this.suppressErrors){var err=new SyntaxError(message,this.filename,this.lexer.yylloc.first_line);throw err.lineNumber=this.lexer.yylloc.first_line,err.fileName=this.filename,err.columnNumber=this.lexer.yylloc.first_column,err}var node=this.ast.prepare("error",this)(message,token,this.lexer.yylloc.first_line,expect); -return this._errors.push(node),node},parser.prototype.error=function(expect){var msg="Parse Error : syntax error";if(token=this.getTokenName(this.token),this.token!==this.EOF){if(isNumber(this.token)){var symbol=this.text();symbol.length>10&&(symbol=symbol.substring(0,7)+"..."),token="'"+symbol+"' ("+token+")"}msg+=", unexpected "+token}var msgExpect="";return expect&&!Array.isArray(expect)&&((isNumber(expect)||1===expect.length)&&(msgExpect=", expecting "+this.getTokenName(expect)),msg+=msgExpect),this.token!==this.EOF,this.raiseError(msg,msgExpect,expect,token)},parser.prototype.node=function(name){return this.ast.prepare(name,this)},parser.prototype.expectEndOfStatement=function(){if(";"===this.token)this.nextWithComments(),this.token===this.tok.T_CLOSE_TAG&&this.nextWithComments();else if(this.token===this.tok.T_CLOSE_TAG)this.nextWithComments();else if(this.token!==this.tok.T_INLINE_HTML&&this.token!==this.EOF)return this.error(";"),!1;return!0};var ignoreStack=["parser.next","parser.ignoreComments","parser.nextWithComments"]; -parser.prototype.showlog=function(){for(var line,stack=(new Error).stack.split("\n"),offset=2;offset"+this.lexer.yytext+"< @-->"+line),this},parser.prototype.expect=function(token){if(Array.isArray(token)){if(token.indexOf(this.token)===-1)return this.error(token),!1}else if(this.token!=token)return this.error(token),!1;return!0},parser.prototype.text=function(){return this.lexer.yytext},parser.prototype.next=function(){return this.debug?(this.showlog(),this.debug=!1,this.nextWithComments().ignoreComments(),this.debug=!0):this.nextWithComments().ignoreComments(),this},parser.prototype.ignoreComments=function(){for(this.debug&&this.showlog();this.token===this.tok.T_COMMENT||this.token===this.tok.T_DOC_COMMENT;)this.nextWithComments(); -return this},parser.prototype.nextWithComments=function(){return this.prev=[this.lexer.yylloc.first_line,this.lexer.yylloc.first_column,this.lexer.offset],this.token=this.lexer.lex()||this.EOF,this.debug&&this.showlog(),this},parser.prototype.is=function(type){return Array.isArray(type)?type.indexOf(this.token)!==-1:this.entries[type].indexOf(this.token)!=-1},[require("./parser/array.js"),require("./parser/class.js"),require("./parser/comment.js"),require("./parser/expr.js"),require("./parser/function.js"),require("./parser/if.js"),require("./parser/loops.js"),require("./parser/main.js"),require("./parser/namespace.js"),require("./parser/scalar.js"),require("./parser/statement.js"),require("./parser/switch.js"),require("./parser/try.js"),require("./parser/utils.js"),require("./parser/variable.js")].forEach(function(ext){for(var k in ext)parser.prototype[k]=ext[k]}),module.exports=parser},{"./parser/array.js":101,"./parser/class.js":102,"./parser/comment.js":103,"./parser/expr.js":104,"./parser/function.js":105, -"./parser/if.js":106,"./parser/loops.js":107,"./parser/main.js":108,"./parser/namespace.js":109,"./parser/scalar.js":110,"./parser/statement.js":111,"./parser/switch.js":112,"./parser/try.js":113,"./parser/utils.js":114,"./parser/variable.js":115}],101:[function(require,module,exports){var ArrayExpr="array",ArrayEntry="entry";module.exports={read_array:function(){var expect=null,shortForm=!1,items=[],result=this.node(ArrayExpr);if(this.token===this.tok.T_ARRAY?(this.next().expect("("),expect=")"):(shortForm=!0,expect="]"),this.next().token!=expect)for(;this.token!=this.EOF&&(items.push(this.read_array_pair_list()),","==this.token)&&(this.next(),this.token!==expect););return this.expect(expect),this.next(),result(shortForm,items)},read_array_pair_list:function(){var result=this.node(ArrayEntry),key=null,value=null;if("&"===this.token)value=this.next().read_variable(!0,!1,!0);else{var expr=this.read_expr();this.token===this.tok.T_DOUBLE_ARROW?(key=expr,value="&"===this.next().token?this.next().read_variable(!0,!1,!0):this.read_expr()):value=expr; -}return result(key,value)},read_dim_offset:function(){return"]"!=this.token&&this.read_expr()}}},{}],102:[function(require,module,exports){module.exports={read_class:function(flag){var result=this.node("class");this.expect(this.tok.T_CLASS),this.next().expect(this.tok.T_STRING);var body,propName=this.text(),propExtends=null,propImplements=null;return this.next().token==this.tok.T_EXTENDS&&(propExtends=this.next().read_namespace_name()),this.token==this.tok.T_IMPLEMENTS&&(propImplements=this.next().read_name_list()),this.expect("{"),body=this.nextWithComments().read_class_body(),result(propName,propExtends,propImplements,body,flag)},read_class_scope:function(){var result=this.token;return result==this.tok.T_FINAL?(this.next(),[0,0,2]):result==this.tok.T_ABSTRACT?(this.next(),[0,0,1]):[0,0,0]},read_class_body:function(){for(var result=[];this.token!==this.EOF&&"}"!==this.token;)if(this.token!==this.tok.T_COMMENT)if(this.token!==this.tok.T_DOC_COMMENT)if(this.token!==this.tok.T_USE){var flags=this.read_member_flags(!1); -if(this.token!==this.tok.T_CONST)if(this.token===this.tok.T_VAR&&(this.next().expect(this.tok.T_VARIABLE),flags[0]=flags[1]=0),this.token===this.tok.T_VARIABLE){var variables=this.read_variable_list(flags);this.expect(";"),this.nextWithComments(),result=result.concat(variables)}else this.token===this.tok.T_FUNCTION?result.push(this.read_function(!1,flags)):(this.error([this.tok.T_CONST,this.tok.T_VARIABLE,this.tok.T_FUNCTION]),this.next());else{var constants=this.read_constant_list(flags);this.expect(";"),this.nextWithComments(),result=result.concat(constants)}}else result=result.concat(this.next().read_trait_use_statement());else result.push(this.read_doc_comment());else result.push(this.read_comment());return this.expect("}"),this.nextWithComments(),result},read_variable_list:function(flags){return this.read_list(function read_variable_declaration(){var result=this.node("property");this.expect(this.tok.T_VARIABLE);var name=this.text().substring(1);return this.next(),";"===this.token||","===this.token?result(name,null,flags):"="===this.token?result(name,this.next().read_expr(),flags):(this.expect([",",";","="]), -result(name,null,flags))},",")},read_constant_list:function(flags){return this.expect(this.tok.T_CONST)&&this.next(),this.read_list(function read_constant_declaration(){var result=this.node("classconstant"),name=null,value=null;return this.expect(this.tok.T_STRING)&&(name=this.text(),this.next()),this.expect("=")&&(value=this.next().read_expr()),result(name,value,flags)},",")},read_member_flags:function(asInterface){var result=[-1,-1,-1];if(this.is("T_MEMBER_FLAGS")){var idx=0,val=0;do{switch(this.token){case this.tok.T_PUBLIC:idx=0,val=0;break;case this.tok.T_PROTECTED:idx=0,val=1;break;case this.tok.T_PRIVATE:idx=0,val=2;break;case this.tok.T_STATIC:idx=1,val=1;break;case this.tok.T_ABSTRACT:idx=2,val=1;break;case this.tok.T_FINAL:idx=2,val=2}asInterface&&(0==idx&&2==val?(this.expect([this.tok.T_PUBLIC,this.tok.T_PROTECTED]),val=-1):2==idx&&1==val&&(this.error(),val=-1)),result[idx]!==-1?this.error():val!==-1&&(result[idx]=val)}while(this.next().is("T_MEMBER_FLAGS"))}return result[0]==-1&&(result[0]=0),result[1]==-1&&(result[1]=0), -result[2]==-1&&(result[2]=0),result},read_interface:function(){var result=this.node("interface"),name=null,body=null,propExtends=null;return this.expect(this.tok.T_INTERFACE)&&this.next(),this.expect(this.tok.T_STRING)&&(name=this.text(),this.next()),this.token===this.tok.T_EXTENDS&&(propExtends=this.next().read_name_list()),this.expect("{")&&(body=this.next().read_interface_body()),result(name,propExtends,body)},read_interface_body:function(){for(var result=[];this.token!==this.EOF&&"}"!==this.token;)if(this.token!==this.tok.T_COMMENT)if(this.token!==this.tok.T_DOC_COMMENT){var flags=this.read_member_flags(!0);if(this.token==this.tok.T_CONST){var constants=this.read_constant_list(flags);this.expect(";")&&this.nextWithComments(),result=result.concat(constants)}else if(this.token===this.tok.T_FUNCTION){var method=this.read_function_declaration(2,flags);method.parseFlags(flags),result.push(method),this.expect(";")&&this.nextWithComments()}else this.error([this.tok.T_CONST,this.tok.T_FUNCTION]),this.next()}else result.push(this.read_doc_comment());else result.push(this.read_comment()); -return this.expect("}")&&this.next(),result},read_trait:function(flag){var result=this.node("trait"),propName=null,propExtends=null,propImplements=null,body=null;return this.expect(this.tok.T_TRAIT)&&this.next(),this.expect(this.tok.T_STRING)&&(propName=this.text()),this.next().token==this.tok.T_EXTENDS&&(propExtends=this.next().read_namespace_name()),this.token==this.tok.T_IMPLEMENTS&&(propImplements=this.next().read_name_list()),this.expect("{")&&(body=this.next().read_class_body()),result(propName,propExtends,propImplements,body)},read_trait_use_statement:function(){for(var node=this.node("traituse"),traits=[this.read_namespace_name()],adaptations=null;","===this.token;)traits.push(this.next().read_namespace_name());if("{"===this.token){for(adaptations=[];this.next().token!==this.EOF&&"}"!==this.token;)adaptations.push(this.read_trait_use_alias()),this.expect(";");this.expect("}")&&this.nextWithComments()}else this.expect(";")&&this.nextWithComments();return node(traits,adaptations)},read_trait_use_alias:function(){ -var node=this.node(),trait=null,method=this.read_namespace_name();if(this.token===this.tok.T_DOUBLE_COLON?this.next().expect(this.tok.T_STRING)&&(trait=method,method=this.text(),this.next()):method=method.name,this.token===this.tok.T_INSTEADOF)return node("traitprecedence",trait,method,this.next().read_name_list());if(this.token===this.tok.T_AS){var flags=!1,alias=null;return this.next().is("T_MEMBER_FLAGS")&&(flags=this.read_member_flags()),this.token===this.tok.T_STRING?(alias=this.text(),this.next()):flags===!1&&this.expect(this.tok.T_STRING),node("traitalias",trait,method,alias,flags)}return this.expect([this.tok.T_AS,this.tok.T_INSTEADOF]),node("traitalias",trait,method,null,null)}}},{}],103:[function(require,module,exports){var docSplit=/^(\s*\*[ \t]*|[ \t]*)(.*)$/gm;module.exports={read_comment:function(){var result=this.node("doc"),lines=[];do{var line=this.text();"#"===line[0]?line=line.substring(1):(line=line.substring(2),"*/"===line.substring(line.length-2)&&(line=line.substring(0,line.length-2))),lines.push(line.trim()); -}while(this.nextWithComments().token===this.tok.T_COMMENT);return result(!1,lines)},read_doc_comment:function(){var result=this.node("doc"),text=this.text();text=text.substring(2,text.length-2);var lines=[];text=text.split(docSplit);for(var i=2;i>",expr,this.next().read_expr());if(this.token===this.tok.T_BOOLEAN_OR)return result("bin","||",expr,this.next().read_expr());if(this.token===this.tok.T_LOGICAL_OR)return result("bin","or",expr,this.next().read_expr());if(this.token===this.tok.T_BOOLEAN_AND)return result("bin","&&",expr,this.next().read_expr());if(this.token===this.tok.T_LOGICAL_AND)return result("bin","and",expr,this.next().read_expr());if(this.token===this.tok.T_LOGICAL_XOR)return result("bin","xor",expr,this.next().read_expr());if(this.token===this.tok.T_IS_IDENTICAL)return result("bin","===",expr,this.next().read_expr());if(this.token===this.tok.T_IS_NOT_IDENTICAL)return result("bin","!==",expr,this.next().read_expr());if(this.token===this.tok.T_IS_EQUAL)return result("bin","==",expr,this.next().read_expr()); -if(this.token===this.tok.T_IS_NOT_EQUAL)return result("bin","!=",expr,this.next().read_expr());if("<"===this.token)return result("bin","<",expr,this.next().read_expr());if(">"===this.token)return result("bin",">",expr,this.next().read_expr());if(this.token===this.tok.T_IS_SMALLER_OR_EQUAL)return result("bin","<=",expr,this.next().read_expr());if(this.token===this.tok.T_IS_GREATER_OR_EQUAL)return result("bin",">=",expr,this.next().read_expr());if(this.token===this.tok.T_SPACESHIP)return result("bin","<=>",expr,this.next().read_expr());if(this.token===this.tok.T_INSTANCEOF)return result("bin","instanceof",expr,this.next().read_expr());if(this.token===this.tok.T_COALESCE)return result("bin","??",expr,this.next().read_expr());if("?"===this.token){var trueArg=null;return":"!==this.next().token&&(trueArg=this.read_expr()),this.expect(":")&&this.next(),result("retif",expr,trueArg,this.read_expr())}return expr},read_expr_item:function(){if("@"===this.token)return this.node("silent")(this.next().read_expr());if("+"===this.token)return this.node("unary")("+",this.next().read_expr()); -if("!"===this.token)return this.node("unary")("!",this.next().read_expr());if("~"===this.token)return this.node("unary")("~",this.next().read_expr());if("-"===this.token){var result=this.node();return this.next(),this.token===this.tok.T_LNUMBER||this.token===this.tok.T_DNUMBER?(result=result("number","-"+this.text()),this.next(),result):result("unary","-",this.read_expr())}if("("===this.token){var node=this.node("parenthesis"),expr=this.next().read_expr();return this.expect(")")&&this.next(),expr=node(expr),this.token===this.tok.T_OBJECT_OPERATOR?this.recursive_variable_chain_scan(expr,!1):this.token===this.tok.T_CURLY_OPEN||"["===this.token?this.read_dereferencable(expr):"("===this.token?this.node("call")(expr,this.read_function_argument_list()):expr}if("`"===this.token)return this.next().read_encapsed_string("`");if(this.token===this.tok.T_LIST){var result=this.node("list"),assign=null,isInner=this.innerList;isInner||(assign=this.node("assign")),this.next().expect("(")&&this.next(),this.innerList||(this.innerList=!0); -for(var assignList=this.read_assignment_list(),hasItem=!1,i=0;i>=");case this.tok.T_INC:return isConst&&this.error("VARIABLE"),this.next(),result("post","+",expr);case this.tok.T_DEC:return isConst&&this.error("VARIABLE"),this.next(),result("post","-",expr)}}else if(this.is("SCALAR"))for(expr=this.read_scalar();this.token!==this.EOF;)if(this.token===this.tok.T_OBJECT_OPERATOR)expr=this.recursive_variable_chain_scan(expr,!1);else if(this.token===this.tok.T_CURLY_OPEN||"["===this.token)expr=this.read_dereferencable(expr);else{ -if("("!==this.token)return expr;expr=this.node("call")(expr,this.read_function_argument_list())}else this.error("EXPR"),this.next();return expr},read_new_expr:function(){var result=this.node("new");if(this.token===this.tok.T_CLASS){var what=this.node("class"),propExtends=null,propImplements=null,body=null,args=[];return"("===this.next().token&&(args=this.read_function_argument_list()),this.token==this.tok.T_EXTENDS&&(propExtends=this.next().read_namespace_name()),this.token==this.tok.T_IMPLEMENTS&&(propImplements=this.next().read_name_list()),this.expect("{")&&(body=this.next().read_class_body()),result(what(null,propExtends,propImplements,body,[0,0,0]),args)}var name=this.read_class_name_reference(),args=[];return"("===this.token&&(args=this.read_function_argument_list()),result(name,args)},read_class_name_reference:function(){if(this.token===this.tok.T_NS_SEPARATOR||this.token===this.tok.T_STRING||this.token===this.tok.T_NAMESPACE){var result=this.read_namespace_name();return this.token===this.tok.T_DOUBLE_COLON&&(result=this.read_static_getter(result)), -result}return this.is("VARIABLE")?this.read_variable(!0,!1,!1):void this.expect([this.tok.T_STRING,"VARIABLE"])},read_assignment_list:function(){return this.read_list(this.read_assignment_list_element,",")},read_assignment_list_element:function(){if(","===this.token||")"===this.token)return null;var result=this.read_expr_item();return this.token===this.tok.T_DOUBLE_ARROW&&(result=["key",result,this.next().read_expr_item()]),result}}},{}],105:[function(require,module,exports){module.exports={is_reference:function(){return"&"==this.token&&(this.next(),!0)},is_variadic:function(){return this.token===this.tok.T_ELLIPSIS&&(this.next(),!0)},read_function:function(closure,flag){var result=this.read_function_declaration(closure?1:flag?2:0,flag&&1===flag[1]);return flag&&1==flag[2]?(result.parseFlags(flag),this.expect(";")&&this.nextWithComments()):(this.expect("{")&&(result.body=this.read_code_block(!1),result.loc&&result.body.loc&&(result.loc.end=result.body.loc.end)),!closure&&flag&&result.parseFlags(flag)),result}, -read_function_declaration:function(type,isStatic){var nodeName="function";1===type?nodeName="closure":2===type&&(nodeName="method");var result=this.node(nodeName);this.expect(this.tok.T_FUNCTION)&&this.next();var isRef=this.is_reference(),name=!1,use=[],returnType=null,nullable=!1;1!==type&&this.expect(this.tok.T_STRING)&&(name=this.text(),this.next()),this.expect("(")&&this.next();var params=this.read_parameter_list();return this.expect(")")&&this.next(),1===type&&this.token===this.tok.T_USE&&(this.next().expect("(")&&this.next(),use=this.read_list(this.read_lexical_var,","),this.expect(")")&&this.next()),":"===this.token&&("?"===this.next().token&&(nullable=!0,this.next()),returnType=this.read_type()),1===type?result(params,isRef,use,returnType,nullable,isStatic):result(name,params,isRef,returnType,nullable)},read_lexical_var:function(){var result=this.node("variable"),isRef=!1;"&"===this.token&&(isRef=!0,this.next()),this.expect(this.tok.T_VARIABLE);var name=this.text().substring(1);return this.next(),result(name,isRef,!1); -},read_parameter_list:function(){var result=[];if(")"!=this.token)for(;this.token!=this.EOF;){if(result.push(this.read_parameter()),","!=this.token){if(")"==this.token)break;this.error([",",")"]);break}this.next()}return result},read_parameter:function(){var node=this.node("parameter"),name=null,value=null,type=null,nullable=!1;"?"===this.token&&(this.next(),nullable=!0),type=this.read_type(),nullable&&!type&&this.raiseError("Expecting a type definition combined with nullable operator");var isRef=this.is_reference(),isVariadic=this.is_variadic();return this.expect(this.tok.T_VARIABLE)&&(name=this.text().substring(1),this.next()),"="==this.token&&(value=this.next().read_expr()),node(name,type,value,isRef,isVariadic,nullable)},read_function_argument_list:function(){var result=[],wasVariadic=!1;if(this.expect("(")&&this.next(),")"!==this.token)for(;this.token!=this.EOF;){var argument=this.read_argument_list();if(argument&&(result.push(argument),"variadic"===argument.kind?wasVariadic=!0:wasVariadic&&this.raiseError("Unexpected argument after a variadic argument")), -","!==this.token)break;this.next()}return this.expect(")")&&this.next(),result},read_argument_list:function(){return this.token===this.tok.T_ELLIPSIS?this.node("variadic")(this.next().read_expr()):this.read_expr()},read_type:function(){var result=this.node("identifier");switch(this.token){case this.tok.T_ARRAY:return this.next(),result(["","array"],!1);case this.tok.T_NAMESPACE:case this.tok.T_NS_SEPARATOR:case this.tok.T_STRING:return this.read_namespace_name();case this.tok.T_CALLABLE:return this.next(),result(["","callable"],!1);default:return null}}}},{}],106:[function(require,module,exports){module.exports={read_if:function(){var result=this.node("if"),body=null,alternate=null,shortForm=!1,test=null;if(test=this.read_if_expr(),":"===this.token){shortForm=!0,this.next(),body=this.node("block");for(var items=[];this.token!==this.EOF&&this.token!==this.tok.T_ENDIF;){if(this.token===this.tok.T_ELSEIF){alternate=this.next().read_elseif_short();break}if(this.token===this.tok.T_ELSE){alternate=this.next().read_else_short(); -break}items.push(this.read_inner_statement())}body=body(null,items),this.expect(this.tok.T_ENDIF)&&this.next(),this.expectEndOfStatement()}else body=this.read_statement(),this.ignoreComments(),this.token===this.tok.T_ELSEIF?alternate=this.next().read_if():this.token===this.tok.T_ELSE&&(alternate=this.next().read_statement());return result(test,body,alternate,shortForm)},read_if_expr:function(){this.expect("(")&&this.next();var result=this.read_expr();return this.expect(")")&&this.next(),result},read_elseif_short:function(){var result=this.node("if"),alternate=null,test=null,body=null,items=[];for(test=this.read_if_expr(),this.expect(":")&&this.next(),body=this.node("block");this.token!=this.EOF&&this.token!==this.tok.T_ENDIF;){if(this.token===this.tok.T_ELSEIF){alternate=this.next().read_elseif_short();break}if(this.token===this.tok.T_ELSE){alternate=this.next().read_else_short();break}items.push(this.read_inner_statement())}return body=body(null,items),result(test,body,alternate,!0)},read_else_short:function(){ -this.expect(":")&&this.next();for(var body=this.node("block"),items=[];this.token!=this.EOF&&this.token!==this.tok.T_ENDIF;)items.push(this.read_inner_statement());return body(null,items)}}},{}],107:[function(require,module,exports){"use strict";module.exports={read_while:function(){var result=this.node("while"),test=null,body=null,shortForm=!1;return this.expect("(")&&this.next(),test=this.read_expr(),this.expect(")")&&this.next(),":"===this.token?(shortForm=!0,body=this.read_short_form(this.tok.T_ENDWHILE)):body=this.read_statement(),result(test,body,shortForm)},read_do:function(){var result=this.node("do"),test=null,body=null;return body=this.read_statement(),this.ignoreComments().expect(this.tok.T_WHILE)&&(this.next().expect("(")&&this.next(),test=this.read_expr(),this.expect(")")&&this.next(),this.expect(";")&&this.next()),result(test,body)},read_for:function(){var result=this.node("for"),init=[],test=[],increment=[],body=null,shortForm=!1;return this.expect("(")&&this.next(),";"!==this.token?(init=this.read_list(this.read_expr,","), -this.expect(";")&&this.next()):this.next(),";"!==this.token?(test=this.read_list(this.read_expr,","),this.expect(";")&&this.next()):this.next(),")"!==this.token?(increment=this.read_list(this.read_expr,","),this.expect(")")&&this.next()):this.next(),":"===this.token?(shortForm=!0,body=this.read_short_form(this.tok.T_ENDFOR)):body=this.read_statement(),result(init,test,increment,body,shortForm)},read_foreach:function(){var result=this.node("foreach"),source=null,key=null,value=null,body=null,shortForm=!1;return this.expect("(")&&this.next(),source=this.read_expr(),this.ignoreComments().expect(this.tok.T_AS)&&(this.next(),value=this.read_foreach_variable(),this.token===this.tok.T_DOUBLE_ARROW&&(key=value,value=this.next().read_foreach_variable())),this.expect(")")&&this.next(),":"===this.token?(shortForm=!0,body=this.read_short_form(this.tok.T_ENDFOREACH)):body=this.read_statement(),result(source,key,value,body,shortForm)},read_foreach_variable:function(){if(this.token===this.tok.T_LIST){var result=this.node("list"); -this.next().expect("(")&&this.next();var assignList=this.read_assignment_list();return this.expect(")")&&this.next(),result(assignList)}return"["===this.token||this.token===this.tok.T_ARRAY?this.read_array():this.read_variable(!1,!1,!1)}}},{}],108:[function(require,module,exports){module.exports={read_start:function(){return this.token==this.tok.T_NAMESPACE?this.read_namespace():this.read_top_statement()}}},{}],109:[function(require,module,exports){"use strict";module.exports={read_namespace:function(){var result=this.node("namespace");if(this.expect(this.tok.T_NAMESPACE)&&this.next(),"{"==this.token){this.currentNamespace=[""];var body=this.nextWithComments().read_top_statements();return this.expect("}")&&this.nextWithComments(),result([""],body,!0)}var name=this.read_namespace_name();if(";"==this.token){this.currentNamespace=name;var body=this.nextWithComments().read_top_statements();return this.expect(this.EOF),result(name.name,body,!1)}if("{"==this.token){this.currentNamespace=name;var body=this.nextWithComments().read_top_statements(); -return this.expect("}")&&this.nextWithComments(),result(name.name,body,!0)}if("("===this.token)return name.resolution=this.ast.identifier.RELATIVE_NAME,name.name=name.name.substring(1),this.node("call")(name,this.read_function_argument_list());this.error(["{",";"]),this.currentNamespace=name;var body=this.read_top_statements();return this.expect(this.EOF),result(name,body,!1)},read_namespace_name:function(){var result=this.node("identifier"),relative=!1;return this.token===this.tok.T_NAMESPACE&&(this.next().expect(this.tok.T_NS_SEPARATOR)&&this.next(),relative=!0),result(this.read_list(this.tok.T_STRING,this.tok.T_NS_SEPARATOR,!0),relative)},read_use_statement:function(){var result=this.node("usegroup"),type=null,items=[],name=null;return this.expect(this.tok.T_USE)&&this.next(),type=this.read_use_type(),items.push(this.read_use_declaration(!1)),","===this.token?items=items.concat(this.next().read_use_declarations(!1)):"{"===this.token&&(name=items[0].name,items=this.next().read_use_declarations(null===type),this.expect("}")&&this.next()), -this.expect(";")&&this.nextWithComments(),result(name,type,items)},read_use_declaration:function(typed){var result=this.node("useitem"),type=null;typed&&(type=this.read_use_type());var name=this.read_namespace_name(),alias=this.read_use_alias();return result(name.name,alias,type)},read_use_declarations:function(typed){for(var result=[this.read_use_declaration(typed)];","===this.token;)result.push(this.next().read_use_declaration(typed));return result},read_use_alias:function(){var result=null;return this.token===this.tok.T_AS&&this.next().expect(this.tok.T_STRING)&&(result=this.text(),this.next()),result},read_use_type:function(){return this.token===this.tok.T_FUNCTION?(this.next(),this.ast.useitem.TYPE_FUNCTION):this.token===this.tok.T_CONST?(this.next(),this.ast.useitem.TYPE_CONST):null}}},{}],110:[function(require,module,exports){var specialChar={"\\r":"\r","\\n":"\n","\\t":"\t","\\v":String.fromCharCode(11),"\\e":String.fromCharCode(27),"\\f":String.fromCharCode(12),"\\\\":"\\","\\$":"$",'\\"':'"',"\\'":"'" -};module.exports={resolve_special_chars:function(text){return text.replace(/\\[rntvef"'\\\$]/g,function(seq){return specialChar[seq]})},read_scalar:function(){if(this.is("T_MAGIC_CONST"))return this.get_magic_constant();switch(this.token){case this.tok.T_CONSTANT_ENCAPSED_STRING:var value=this.node("string"),text=this.text(),isDoubleQuote='"'===text[0];return text=text.substring(1,text.length-1),this.next(),value=value(isDoubleQuote,this.resolve_special_chars(text)),this.token===this.tok.T_DOUBLE_COLON?this.read_static_getter(value):value;case this.tok.T_START_HEREDOC:if("ST_NOWDOC"===this.lexer.curCondition){var node=this.node("nowdoc"),value=this.next().text(),lastCh=value[value.length-1];return"\n"===lastCh?value="\r"===value[value.length-2]?value.substring(0,value.length-2):value.substring(0,value.length-1):"\r"===lastCh&&(value=value.substring(0,value.length-1)),this.expect(this.tok.T_ENCAPSED_AND_WHITESPACE)&&this.next(),node=node(value,this.lexer.heredoc_label),this.expect(this.tok.T_END_HEREDOC)&&this.next(), -node}return this.next().read_encapsed_string(this.tok.T_END_HEREDOC);case'"':return this.next().read_encapsed_string('"');case'b"':case'B"':var node=this.node("cast"),what=this.next().read_encapsed_string('"');return node("binary",what);case this.tok.T_LNUMBER:case this.tok.T_DNUMBER:var result=this.node("number"),value=this.text();return this.next(),result=result(value);case this.tok.T_ARRAY:case"[":return this.read_array();default:var err=this.error("SCALAR");return this.next(),err}},read_dereferencable:function(expr){var result,node=this.node("offsetlookup");if("["===this.token){var offset=this.next().read_expr();this.expect("]")&&this.next(),result=node(expr,offset)}else if(this.token===this.tok.T_DOLLAR_OPEN_CURLY_BRACES){var offset=this.read_encapsed_string_item();result=node(expr,offset)}return result},read_encapsed_string_item:function(){var result=this.node();if(this.token===this.tok.T_ENCAPSED_AND_WHITESPACE){var text=this.text();this.next(),result=result("string",!1,this.resolve_special_chars(text)); -}else if(this.token===this.tok.T_DOLLAR_OPEN_CURLY_BRACES){var name=null;if(this.next().token===this.tok.T_STRING_VARNAME){var varName=this.text();if(name=this.node("variable"),this.next(),"["===this.token){name=name(varName,!1);var node=this.node("offsetlookup"),offset=this.next().read_expr();this.expect("]")&&this.next(),name=node(name,offset)}else name=varName}else name=this.read_expr();this.expect("}")&&this.next(),result=result("variable",name,!1,!0)}else if(this.token===this.tok.T_CURLY_OPEN)result=this.next().read_variable(!1,!1,!1),this.expect("}")&&this.next();else if(this.token===this.tok.T_VARIABLE){if(result=this.read_simple_variable(!1),"["===this.token){var node=this.node("offsetlookup"),offset=this.next().read_encaps_var_offset();this.expect("]")&&this.next(),result=node(result,offset)}if(this.token===this.tok.T_OBJECT_OPERATOR){var node=this.node("propertylookup"),what=this.node("constref");this.next().expect(this.tok.T_STRING);var name=this.text();this.next(),result=node(result,what(name))}}else{ -this.expect(this.tok.T_ENCAPSED_AND_WHITESPACE);var value=this.text();this.next(),result=result("string",!1,value)}return result},read_encapsed_string:function(expect){var node=this.node("encapsed"),value=[],type=null;for(type="`"===expect?this.ast.encapsed.TYPE_SHELL:'"'===expect?this.ast.encapsed.TYPE_STRING:this.ast.encapsed.TYPE_HEREDOC;this.token!==expect&&this.token!==this.EOF;)value.push(this.read_encapsed_string_item());return this.expect(expect)&&this.next(),node=node(value,type),expect===this.tok.T_END_HEREDOC&&(node.label=this.lexer.heredoc_label),node},get_magic_constant:function(){var result=this.node("magic"),name=this.text();return this.next(),result(name)}}},{}],111:[function(require,module,exports){module.exports={read_top_statements:function(){for(var result=[];this.token!==this.EOF&&"}"!==this.token;){var statement=this.read_top_statement();statement&&(Array.isArray(statement)?result=result.concat(statement):result.push(statement))}return result},read_top_statement:function(){switch(this.token){ -case this.tok.T_FUNCTION:return this.read_function(!1,!1);case this.tok.T_ABSTRACT:case this.tok.T_FINAL:var flag=this.read_class_scope();return this.token===this.tok.T_CLASS?this.read_class(flag):(this.error(this.tok.T_CLASS),this.next(),null);case this.tok.T_CLASS:return this.read_class([0,0,0]);case this.tok.T_INTERFACE:return this.read_interface();case this.tok.T_TRAIT:return this.read_trait();case this.tok.T_USE:return this.read_use_statement();case this.tok.T_CONST:return this.next().read_const_list();case this.tok.T_NAMESPACE:return this.read_namespace();case this.tok.T_HALT_COMPILER:var result=this.node("halt");return this.next().expect("(")&&this.next(),this.expect(")")&&this.next(),this.expect(";"),this.lexer.done=!0,result(this.lexer._input.substring(this.lexer.offset));default:return this.read_statement()}},read_inner_statements:function(){for(var result=[];this.token!=this.EOF&&"}"!==this.token;){var statement=this.read_inner_statement();statement&&(Array.isArray(statement)?result=result.concat(statement):result.push(statement)); -}return result},read_const_list:function(){var result=this.read_list(function(){this.expect(this.tok.T_STRING);var result=this.node("constant"),name=this.text();return this.next().expect("=")?result(name,this.next().read_expr()):result(name,null)},",",!1);return this.expectEndOfStatement(),result},read_declare_list:function(){for(var result={};this.token!=this.EOF&&")"!==this.token;){this.expect(this.tok.T_STRING);var name=this.text().toLowerCase();if(this.next().expect("=")?result[name]=this.next().read_expr():result[name]=null,","!==this.token)break;this.next()}return result},read_inner_statement:function(){switch(this.token){case this.tok.T_FUNCTION:return this.read_function(!1,!1);case this.tok.T_ABSTRACT:case this.tok.T_FINAL:var flag=this.read_class_scope();return this.token===this.tok.T_CLASS?this.read_class(flag):(this.error(this.tok.T_CLASS),this.next(),null);case this.tok.T_CLASS:return this.read_class([0,0,0]);case this.tok.T_INTERFACE:return this.read_interface();case this.tok.T_TRAIT:return this.read_trait(); -case this.tok.T_HALT_COMPILER:this.raiseError("__HALT_COMPILER() can only be used from the outermost scope");var node=this.node("halt");return this.next().expect("(")&&this.next(),this.expect(")")&&this.next(),node=node(this.lexer._input.substring(this.lexer.offset)),this.expect(";")&&this.next(),node;default:return this.read_statement()}},read_statement:function(){switch(this.token){case"{":return this.read_code_block(!1);case this.tok.T_IF:return this.next().read_if();case this.tok.T_SWITCH:return this.read_switch();case this.tok.T_FOR:return this.next().read_for();case this.tok.T_FOREACH:return this.next().read_foreach();case this.tok.T_WHILE:return this.next().read_while();case this.tok.T_DO:return this.next().read_do();case this.tok.T_COMMENT:return this.read_comment();case this.tok.T_DOC_COMMENT:return this.read_doc_comment();case this.tok.T_RETURN:var result=this.node("return"),expr=null;return this.next().is("EOS")||(expr=this.read_expr()),this.expectEndOfStatement(),result(expr);case this.tok.T_BREAK: -case this.tok.T_CONTINUE:var result=this.node(this.token===this.tok.T_CONTINUE?"continue":"break"),level=null;return this.next(),";"!==this.token&&this.token!==this.tok.T_CLOSE_TAG&&(level=this.read_expr()),this.expectEndOfStatement(),result(level);case this.tok.T_GLOBAL:var result=this.node("global"),items=this.next().read_list(this.read_simple_variable,",");return this.expectEndOfStatement(),result(items);case this.tok.T_STATIC:var current=[this.token,this.lexer.getState()],result=this.node("static");if(this.next().token===this.tok.T_DOUBLE_COLON){this.lexer.tokens.push(current);var expr=this.next().read_expr();return this.expect(";")&&this.nextWithComments(),expr}if(this.token===this.tok.T_FUNCTION)return this.read_function(!0,[0,1,0]);var items=this.read_variable_declarations();return this.expectEndOfStatement(),result(items);case this.tok.T_ECHO:var result=this.node("echo"),args=this.next().read_list(this.read_expr,",");return this.expectEndOfStatement(),result(args);case this.tok.T_INLINE_HTML:var result=this.node("inline"),value=this.text(); -return this.next(),result(value);case this.tok.T_UNSET:var result=this.node("unset");this.next().expect("(")&&this.next();var items=this.read_list(this.read_variable,",");return this.expect(")")&&this.next(),this.expect(";")&&this.nextWithComments(),result(items);case this.tok.T_DECLARE:var what,mode,result=this.node("declare"),body=[];if(this.next().expect("(")&&this.next(),what=this.read_declare_list(),this.expect(")")&&this.next(),":"===this.token){for(this.nextWithComments();this.token!=this.EOF&&this.token!==this.tok.T_ENDDECLARE;)body.push(this.read_top_statement());this.expect(this.tok.T_ENDDECLARE)&&this.next(),this.expectEndOfStatement(),mode=this.ast.declare.MODE_SHORT}else if("{"===this.token){for(this.nextWithComments();this.token!=this.EOF&&"}"!==this.token;)body.push(this.read_top_statement());this.expect("}")&&this.next(),mode=this.ast.declare.MODE_BLOCK}else{for(this.expect(";")&&this.nextWithComments();this.token!=this.EOF&&this.token!==this.tok.T_DECLARE;)body.push(this.read_top_statement());mode=this.ast.declare.MODE_NONE; -}return result(what,body,mode);case this.tok.T_TRY:return this.read_try();case this.tok.T_THROW:var result=this.node("throw"),expr=this.next().read_expr();return this.expectEndOfStatement(),result(expr);case";":case this.tok.T_CLOSE_TAG:return this.next(),null;case this.tok.T_STRING:var current=[this.token,this.lexer.getState()],label=this.text();if(":"===this.next().token){var result=this.node("label");return this.next(),result(label)}this.lexer.tokens.push(current);var expr=this.next().read_expr();return this.expectEndOfStatement(),expr;case this.tok.T_GOTO:var result=this.node("goto"),label=null;return this.next().expect(this.tok.T_STRING)&&(label=this.text(),this.next().expectEndOfStatement()),result(label);default:var expr=this.read_expr();return this.expectEndOfStatement(),expr}},read_code_block:function(top){var result=this.node("block");this.expect("{")&&this.nextWithComments();var body=top?this.read_top_statements():this.read_inner_statements();return this.expect("}")&&this.nextWithComments(),result(null,body); -}}},{}],112:[function(require,module,exports){"use strict";module.exports={read_switch:function(){this.expect(this.tok.T_SWITCH)&&this.next();var test,body,shortForm,result=this.node("switch");return this.expect("(")&&this.next(),test=this.read_expr(),this.expect(")")&&this.next(),shortForm=":"===this.token,body=this.read_switch_case_list(),result(test,body,shortForm)},read_switch_case_list:function(){var expect=null,result=this.node("block"),items=[];for("{"===this.token?expect="}":":"===this.token?expect=this.tok.T_ENDSWITCH:this.expect(["{",":"]),";"===this.next().token&&this.next(),this.token===this.tok.T_CLOSE_TAG&&this.next();this.token!==this.EOF&&this.token!==expect;)items.push(this.read_case_list(expect));return this.expect(expect)&&this.next(),expect===this.tok.T_ENDSWITCH&&this.expectEndOfStatement(),result(null,items)},read_case_list:function(stopToken){var result=this.node("case"),test=null,body=null,items=[];for(this.token===this.tok.T_CASE?test=this.next().read_expr():this.token===this.tok.T_DEFAULT?this.next():this.expect([this.tok.T_CASE,this.tok.T_DEFAULT]), -this.expect([":",";"])&&this.next(),body=this.node("block");this.token!=this.EOF&&this.token!==stopToken&&this.token!==this.tok.T_CASE&&this.token!==this.tok.T_DEFAULT;)items.push(this.read_inner_statement());return result(test,items.length>0?body(null,items):null)}}},{}],113:[function(require,module,exports){module.exports={read_try:function(){this.expect(this.tok.T_TRY);var body,result=this.node("try"),always=null,catches=[];for(body=this.next().read_statement();this.ignoreComments().token===this.tok.T_CATCH;){var item=this.node("catch"),what=[],variable=null;this.next().expect("(")&&this.next(),what=this.read_list(this.read_namespace_name,"|",!1),variable=this.read_variable(!0,!1,!1),this.expect(")"),catches.push(item(this.next().read_statement(),what,variable))}return this.token===this.tok.T_FINALLY&&(always=this.next().read_statement()),result(body,catches,always)}}},{}],114:[function(require,module,exports){"use strict";module.exports={read_short_form:function(token){var body=this.node("block"),items=[];for(this.expect(":")&&this.next();this.token!=this.EOF&&this.token!==token;)items.push(this.read_inner_statement()); -return this.expect(token)&&this.next(),this.expectEndOfStatement(),body(null,items)},read_list:function(item,separator,preserveFirstSeparator){var result=[];if(this.token==separator&&(preserveFirstSeparator&&result.push(""),this.next()),"function"==typeof item){do if(result.push(item.apply(this,[])),this.token!=separator)break;while(this.next().token!=this.EOF)}else{if(!this.expect(item))return[];for(result.push(this.text());this.next().token!=this.EOF&&this.token==separator&&this.next().token==item;)result.push(this.text())}return result},read_name_list:function(){return this.read_list(this.read_namespace_name,",",!1)},read_variable_declarations:function(){return this.read_list(function(){var node=this.node("assign"),variable=this.node("variable");if(this.expect(this.tok.T_VARIABLE)){var name=this.text().substring(1);this.next(),variable=variable(name,!1,!1)}else variable=variable("#ERR",!1,!1);return"="===this.token?node(variable,this.next().read_expr()):variable},",")}}},{}],115:[function(require,module,exports){ -"use strict";module.exports={read_variable:function(read_only,encapsed,byref){var result;if(byref||"&"!==this.token||(byref=!0,this.next()),this.is([this.tok.T_VARIABLE,"$"]))result=this.read_reference_variable(encapsed,byref);else if(this.is([this.tok.T_NS_SEPARATOR,this.tok.T_STRING,this.tok.T_NAMESPACE])){result=this.node();var name=this.read_namespace_name();if(this.token!=this.tok.T_DOUBLE_COLON&&"("!=this.token){var literal=name.name.toLowerCase();result="true"===literal?result("boolean",!0):"false"===literal?result("boolean",!1):result("constref",name)}else result=name}else this.token===this.tok.T_STATIC?(result=this.node("constref"),this.next(),result=result("static")):this.expect("VARIABLE");return this.token===this.tok.T_DOUBLE_COLON&&(result=this.read_static_getter(result,encapsed)),this.recursive_variable_chain_scan(result,read_only,encapsed)},read_static_getter:function(what,encapsed){var result=this.node("staticlookup"),offset=null;if(this.next().is([this.tok.T_VARIABLE,"$"]))offset=this.read_reference_variable(encapsed,!1);else if(this.token===this.tok.T_STRING||this.token===this.tok.T_CLASS){ -offset=this.node("constref");var name=this.text();this.next(),offset=offset(name)}else{this.error([this.tok.T_VARIABLE,this.tok.T_STRING]),offset=this.node("constref");var name=this.text();this.next(),offset=offset(name)}return result(what,offset)},recursive_variable_chain_scan:function(result,read_only,encapsed){recursive_scan_loop:for(;this.token!=this.EOF;)switch(this.token){case"(":if(read_only)return result;result=this.node("call")(result,this.read_function_argument_list());break;case"[":var node=this.node("offsetlookup");this.next();var offset=!1;encapsed?(offset=this.read_encaps_var_offset(),this.expect("]")&&this.next()):"]"!==this.token?(offset=this.read_expr(),this.expect("]")&&this.next()):this.next(),result=node(result,offset);break;case this.tok.T_OBJECT_OPERATOR:var node=this.node("propertylookup"),what=null;switch(this.next().token){case this.tok.T_STRING:what=this.node("constref");var name=this.text();if(this.next(),what=what(name),this.token===this.tok.T_VARIABLE){var inner=this.node("variable"); -name=this.text().substring(1),this.next(),what=this.node("encapsed")([what,inner(name,!1,!1)],"offset"),what.loc&&what.value[0].loc&&(what.loc.start=what.value[0].loc.start)}else if("{"===this.token){var expr=this.next().read_expr();this.expect("}")&&this.next(),what=this.node("encapsed")([what,expr],"offset"),what.loc&&what.value[0].loc&&(what.loc.start=what.value[0].loc.start)}break;case this.tok.T_VARIABLE:what=this.node("variable");var name=this.text().substring(1);this.next(),what=what(name,!1,!1);break;case"$":this.next().expect(["{",this.tok.T_VARIABLE]),"{"===this.token?(what=this.next().read_expr(),this.expect("}")&&this.next()):what=this.read_expr();break;case"{":what=this.next().read_expr(),this.expect("}")&&this.next();break;default:this.error([this.tok.T_STRING,this.tok.T_VARIABLE]),what=this.node("constref");var name=this.text();this.next(),what=what(name)}result=node(result,what);break;default:break recursive_scan_loop}return result},read_encaps_var_offset:function(){var offset=this.node();if(this.token===this.tok.T_STRING){ -var text=this.text(),isDblQuote='"'===text[0];text=text.substring(1,text.length-1),this.next(),offset=offset("string",isDblQuote,this.resolve_special_chars(text))}else if(this.token===this.tok.T_NUM_STRING){var num=this.text();this.next(),offset=offset("number",num)}else if(this.token===this.tok.T_VARIABLE){var name=this.text().substring(1);this.next(),offset=offset("variable",name,!1,!1)}else{this.expect([this.tok.T_STRING,this.tok.T_NUM_STRING,this.tok.T_VARIABLE]);var text=this.text();this.next(),offset=offset("string",!1,text)}return offset},read_reference_variable:function(encapsed,byref){for(var result=this.read_simple_variable(byref);this.token!=this.EOF;){var node=this.node();if("["==this.token){var offset=null;offset=encapsed?this.next().read_encaps_var_offset():"]"===this.next().token?null:this.read_dim_offset(),this.expect("]")&&this.next(),result=node("offsetlookup",result,offset)}else{if("{"!=this.token||encapsed)break;var offset=this.next().read_expr();this.expect("}")&&this.next(),result=node("offsetlookup",result,offset); -}}return result},read_simple_variable:function(byref){var result=this.node("variable");if(this.expect([this.tok.T_VARIABLE,"$"])&&this.token===this.tok.T_VARIABLE){var name=this.text().substring(1);this.next(),result=result(name,byref,!1)}else switch("$"===this.token&&this.next(),this.token){case"{":var expr=this.next().read_expr();this.expect("}")&&this.next(),result=result(expr,byref,!0);break;case"$":result=result(this.read_simple_variable(!1),byref);break;case this.tok.T_VARIABLE:var name=this.text().substring(1),node=this.node("variable");this.next(),result=result(node(name,!1,!1),byref,!1);break;default:this.error(["{","$",this.tok.T_VARIABLE]);var name=this.text();this.next(),result=result(name,byref,!1)}return result}}},{}],116:[function(require,module,exports){module.exports={values:{101:"T_HALT_COMPILER",102:"T_USE",103:"T_ENCAPSED_AND_WHITESPACE",104:"T_OBJECT_OPERATOR",105:"T_STRING",106:"T_DOLLAR_OPEN_CURLY_BRACES",107:"T_STRING_VARNAME",108:"T_CURLY_OPEN",109:"T_NUM_STRING",110:"T_ISSET",111:"T_EMPTY", -112:"T_INCLUDE",113:"T_INCLUDE_ONCE",114:"T_EVAL",115:"T_REQUIRE",116:"T_REQUIRE_ONCE",117:"T_NAMESPACE",118:"T_NS_SEPARATOR",119:"T_AS",120:"T_IF",121:"T_ENDIF",122:"T_WHILE",123:"T_DO",124:"T_FOR",125:"T_SWITCH",126:"T_BREAK",127:"T_CONTINUE",128:"T_RETURN",129:"T_GLOBAL",130:"T_STATIC",131:"T_ECHO",132:"T_INLINE_HTML",133:"T_UNSET",134:"T_FOREACH",135:"T_DECLARE",136:"T_TRY",137:"T_THROW",138:"T_GOTO",139:"T_FINALLY",140:"T_CATCH",141:"T_ENDDECLARE",142:"T_LIST",143:"T_CLONE",144:"T_PLUS_EQUAL",145:"T_MINUS_EQUAL",146:"T_MUL_EQUAL",147:"T_DIV_EQUAL",148:"T_CONCAT_EQUAL",149:"T_MOD_EQUAL",150:"T_AND_EQUAL",151:"T_OR_EQUAL",152:"T_XOR_EQUAL",153:"T_SL_EQUAL",154:"T_SR_EQUAL",155:"T_INC",156:"T_DEC",157:"T_BOOLEAN_OR",158:"T_BOOLEAN_AND",159:"T_LOGICAL_OR",160:"T_LOGICAL_AND",161:"T_LOGICAL_XOR",162:"T_SL",163:"T_SR",164:"T_IS_IDENTICAL",165:"T_IS_NOT_IDENTICAL",166:"T_IS_EQUAL",167:"T_IS_NOT_EQUAL",168:"T_IS_SMALLER_OR_EQUAL",169:"T_IS_GREATER_OR_EQUAL",170:"T_INSTANCEOF",171:"T_INT_CAST",172:"T_DOUBLE_CAST", -173:"T_STRING_CAST",174:"T_ARRAY_CAST",175:"T_OBJECT_CAST",176:"T_BOOL_CAST",177:"T_UNSET_CAST",178:"T_EXIT",179:"T_PRINT",180:"T_YIELD",181:"T_YIELD_FROM",182:"T_FUNCTION",183:"T_DOUBLE_ARROW",184:"T_DOUBLE_COLON",185:"T_ARRAY",186:"T_CALLABLE",187:"T_CLASS",188:"T_ABSTRACT",189:"T_TRAIT",190:"T_FINAL",191:"T_EXTENDS",192:"T_INTERFACE",193:"T_IMPLEMENTS",194:"T_VAR",195:"T_PUBLIC",196:"T_PROTECTED",197:"T_PRIVATE",198:"T_CONST",199:"T_NEW",200:"T_INSTEADOF",201:"T_ELSEIF",202:"T_ELSE",203:"T_ENDSWITCH",204:"T_CASE",205:"T_DEFAULT",206:"T_ENDFOR",207:"T_ENDFOREACH",208:"T_ENDWHILE",209:"T_CONSTANT_ENCAPSED_STRING",210:"T_LNUMBER",211:"T_DNUMBER",212:"T_LINE",213:"T_FILE",214:"T_DIR",215:"T_TRAIT_C",216:"T_METHOD_C",217:"T_FUNC_C",218:"T_NS_C",219:"T_START_HEREDOC",220:"T_END_HEREDOC",221:"T_CLASS_C",222:"T_VARIABLE",223:"T_OPEN_TAG",224:"T_OPEN_TAG_WITH_ECHO",225:"T_CLOSE_TAG",226:"T_WHITESPACE",227:"T_COMMENT",228:"T_DOC_COMMENT",229:"T_ELLIPSIS",230:"T_COALESCE",231:"T_POW",232:"T_POW_EQUAL",233:"T_SPACESHIP" -},names:{T_HALT_COMPILER:101,T_USE:102,T_ENCAPSED_AND_WHITESPACE:103,T_OBJECT_OPERATOR:104,T_STRING:105,T_DOLLAR_OPEN_CURLY_BRACES:106,T_STRING_VARNAME:107,T_CURLY_OPEN:108,T_NUM_STRING:109,T_ISSET:110,T_EMPTY:111,T_INCLUDE:112,T_INCLUDE_ONCE:113,T_EVAL:114,T_REQUIRE:115,T_REQUIRE_ONCE:116,T_NAMESPACE:117,T_NS_SEPARATOR:118,T_AS:119,T_IF:120,T_ENDIF:121,T_WHILE:122,T_DO:123,T_FOR:124,T_SWITCH:125,T_BREAK:126,T_CONTINUE:127,T_RETURN:128,T_GLOBAL:129,T_STATIC:130,T_ECHO:131,T_INLINE_HTML:132,T_UNSET:133,T_FOREACH:134,T_DECLARE:135,T_TRY:136,T_THROW:137,T_GOTO:138,T_FINALLY:139,T_CATCH:140,T_ENDDECLARE:141,T_LIST:142,T_CLONE:143,T_PLUS_EQUAL:144,T_MINUS_EQUAL:145,T_MUL_EQUAL:146,T_DIV_EQUAL:147,T_CONCAT_EQUAL:148,T_MOD_EQUAL:149,T_AND_EQUAL:150,T_OR_EQUAL:151,T_XOR_EQUAL:152,T_SL_EQUAL:153,T_SR_EQUAL:154,T_INC:155,T_DEC:156,T_BOOLEAN_OR:157,T_BOOLEAN_AND:158,T_LOGICAL_OR:159,T_LOGICAL_AND:160,T_LOGICAL_XOR:161,T_SL:162,T_SR:163,T_IS_IDENTICAL:164,T_IS_NOT_IDENTICAL:165,T_IS_EQUAL:166,T_IS_NOT_EQUAL:167,T_IS_SMALLER_OR_EQUAL:168, -T_IS_GREATER_OR_EQUAL:169,T_INSTANCEOF:170,T_INT_CAST:171,T_DOUBLE_CAST:172,T_STRING_CAST:173,T_ARRAY_CAST:174,T_OBJECT_CAST:175,T_BOOL_CAST:176,T_UNSET_CAST:177,T_EXIT:178,T_PRINT:179,T_YIELD:180,T_YIELD_FROM:181,T_FUNCTION:182,T_DOUBLE_ARROW:183,T_DOUBLE_COLON:184,T_ARRAY:185,T_CALLABLE:186,T_CLASS:187,T_ABSTRACT:188,T_TRAIT:189,T_FINAL:190,T_EXTENDS:191,T_INTERFACE:192,T_IMPLEMENTS:193,T_VAR:194,T_PUBLIC:195,T_PROTECTED:196,T_PRIVATE:197,T_CONST:198,T_NEW:199,T_INSTEADOF:200,T_ELSEIF:201,T_ELSE:202,T_ENDSWITCH:203,T_CASE:204,T_DEFAULT:205,T_ENDFOR:206,T_ENDFOREACH:207,T_ENDWHILE:208,T_CONSTANT_ENCAPSED_STRING:209,T_LNUMBER:210,T_DNUMBER:211,T_LINE:212,T_FILE:213,T_DIR:214,T_TRAIT_C:215,T_METHOD_C:216,T_FUNC_C:217,T_NS_C:218,T_START_HEREDOC:219,T_END_HEREDOC:220,T_CLASS_C:221,T_VARIABLE:222,T_OPEN_TAG:223,T_OPEN_TAG_WITH_ECHO:224,T_CLOSE_TAG:225,T_WHITESPACE:226,T_COMMENT:227,T_DOC_COMMENT:228,T_ELLIPSIS:229,T_COALESCE:230,T_POW:231,T_POW_EQUAL:232,T_SPACESHIP:233}}},{}],"php-parser":[function(require,module,exports){ -function combine(src,to){for(var keys=Object.keys(src),i=keys.length;i--;){var k=keys[i],val=src[k];null===val?delete to[k]:"function"==typeof val?to[k]=val.bind(to):Array.isArray(val)?to[k]=Array.isArray(to[k])?to[k].concat(val):val:"object"==typeof val?to[k]="object"==typeof to[k]?combine(val,to[k]):val:to[k]=val}return to}var lexer=require("./lexer"),parser=require("./parser"),tokens=require("./tokens"),AST=require("./ast"),engine=function(options){return"function"==typeof this?new this(options):(this.tokens=tokens,this.lexer=new lexer(this),this.ast=new AST,this.parser=new parser(this.lexer,this.ast),void(options&&"object"==typeof options&&combine(options,this)))};engine.create=function(options){return new engine(options)},engine.parseEval=function(buffer,options){var self=new engine(options);return self.parseEval(buffer)},engine.prototype.parseEval=function(buffer){return this.lexer.mode_eval=!0,this.lexer.all_tokens=!1,this.parser.parse(buffer,"eval")},engine.parseCode=function(buffer,filename,options){"object"==typeof filename&&(options=filename, -filename="unknown");var self=new engine(options);return self.parseCode(buffer,filename)},engine.prototype.parseCode=function(buffer,filename){return this.lexer.mode_eval=!1,this.lexer.all_tokens=!1,this.parser.parse(buffer,filename)},engine.tokenGetAll=function(buffer,options){var self=new engine(options);return self.tokenGetAll(buffer)},engine.prototype.tokenGetAll=function(buffer){this.lexer.mode_eval=!1,this.lexer.all_tokens=!0;var EOF=this.lexer.EOF,names=this.tokens.values;this.lexer.setInput(buffer);for(var token=this.lexer.lex()||EOF,result=[];token!=EOF;){var entry=this.lexer.yytext;names.hasOwnProperty(token)&&(entry=[names[token],entry,this.lexer.yylloc.first_line]),result.push(entry),token=this.lexer.lex()||EOF}return result},module.exports=engine},{"./ast":2,"./lexer":91,"./parser":100,"./tokens":116}]},{},[]); -//# sourceMappingURL=php-parser.min.js.map \ No newline at end of file diff --git a/dist/php-parser.min.js.map b/dist/php-parser.min.js.map deleted file mode 100644 index dcd9fe398..000000000 --- a/dist/php-parser.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["php-parser.js"],"names":["require","e","t","n","r","s","o","u","a","i","f","Error","code","l","exports","call","length","1","module","defaultSetTimout","defaultClearTimeout","runTimeout","fun","cachedSetTimeout","setTimeout","this","runClearTimeout","marker","cachedClearTimeout","clearTimeout","cleanUpNextTick","draining","currentQueue","queue","concat","queueIndex","drainQueue","timeout","len","run","Item","array","noop","process","nextTick","args","Array","arguments","push","prototype","apply","title","browser","env","argv","version","versions","on","addListener","once","off","removeListener","removeAllListeners","emit","binding","name","cwd","chdir","dir","umask","2","Location","Position","AST","withPositions","withSource","position","parser","lexer","yylloc","first_line","first_column","first_offset","precedence","forEach","list","index","operator","resolvePrecedence","result","buffer","kind","right","lLevel","type","rLevel","left","test","what","falseExpr","prepare","start","self","location","slice","src","_input","substring","offset","prev_offset","prev_line","prev_column","shift","node","Object","create","ctor","constructor","toLowerCase","./ast/array","./ast/assign","./ast/bin","./ast/block","./ast/boolean","./ast/break","./ast/call","./ast/case","./ast/cast","./ast/catch","./ast/class","./ast/classconstant","./ast/clone","./ast/closure","./ast/constant","./ast/constref","./ast/continue","./ast/declaration","./ast/declare","./ast/do","./ast/doc","./ast/echo","./ast/empty","./ast/encapsed","./ast/entry","./ast/error","./ast/eval","./ast/exit","./ast/expression","./ast/for","./ast/foreach","./ast/function","./ast/global","./ast/goto","./ast/halt","./ast/identifier","./ast/if","./ast/include","./ast/inline","./ast/interface","./ast/isset","./ast/label","./ast/list","./ast/literal","./ast/location","./ast/lookup","./ast/magic","./ast/method","./ast/namespace","./ast/new","./ast/node","./ast/nowdoc","./ast/number","./ast/offsetlookup","./ast/operation","./ast/parameter","./ast/parenthesis","./ast/position","./ast/post","./ast/pre","./ast/print","./ast/program","./ast/property","./ast/propertylookup","./ast/retif","./ast/return","./ast/silent","./ast/statement","./ast/static","./ast/staticlookup","./ast/string","./ast/switch","./ast/sys","./ast/throw","./ast/trait","./ast/traitalias","./ast/traitprecedence","./ast/traituse","./ast/try","./ast/unary","./ast/unset","./ast/usegroup","./ast/useitem","./ast/variable","./ast/variadic","./ast/while","./ast/yield","./ast/yieldfrom","3","Expr","KIND","extends","shortForm","items","./expression","4","Statement","Assign","./statement","5","Operation","Bin","./operation","6","Block","children","7","Literal","Boolean","value","./literal","8","Node","Break","level","./node","9","Call","10","Case","body","11","Cast","12","Catch","variable","13","Declaration","Class","ext","impl","flags","isAnonymous","implements","parseFlags","./declaration","14","Constant","ClassConstant","./constant","15","Clone","16","Closure","byref","uses","nullable","isStatic","17","18","ConstRef","identifier","19","Continue","20","IS_PUBLIC","IS_PROTECTED","IS_PRIVATE","isAbstract","isFinal","visibility","21","Declare","mode","MODE_SHORT","MODE_BLOCK","MODE_NONE","./block","22","Do","23","Doc","isDoc","lines","24","Sys","Echo","./sys","25","Empty","26","Encapsed","TYPE_STRING","TYPE_SHELL","TYPE_HEREDOC","TYPE_OFFSET","27","Entry","key","28","message","token","line","expected","29","Eval","source","30","Exit","status","31","Expression","32","For","init","increment","33","Foreach","34","fn","_Function","35","Global","36","Goto","label","37","Halt","after","38","Identifier","isRelative","resolution","RELATIVE_NAME","UNQUALIFIED_NAME","FULL_QUALIFIED_NAME","QUALIFIED_NAME","join","39","If","alternate","40","Include","target","41","Inline","42","Interface","43","Isset","44","Label","45","List","46","47","end","48","Lookup","49","Magic","50","Method","./function","51","Namespace","withBrackets","./identifier","52","New","53","loc","54","Nowdoc","55","_Number","Number","56","OffsetLookup","./lookup","57","58","Parameter","isRef","isVariadic","variadic","59","Parenthesis","inner","60","column","61","Post","62","Pre","63","Print","64","Program","errors","65","Property","66","PropertyLookup","67","RetIf","trueExpr","68","Return","expr","69","Silent","70","71","Static","72","StaticLookup","73","String","isDoubleQuote","74","Switch","75","76","Throw","77","Trait","78","TraitAlias","trait","method","as","79","TraitPrecedence","instead","80","TraitUse","traits","adaptations","81","Try","catches","always","82","Unary","83","Unset","84","UseGroup","85","UseItem","alias","TYPE_CONST","TYPE_FUNCTION","86","Variable","curly","87","Variadic","88","While","89","Yield","90","YieldFrom","91","engine","tok","tokens","names","EOF","debug","all_tokens","comment_tokens","mode_eval","asp_tags","short_tags","yyprevcol","keywords","__class__","T_CLASS_C","__trait__","T_TRAIT_C","__function__","T_FUNC_C","__method__","T_METHOD_C","__line__","T_LINE","__file__","T_FILE","__dir__","T_DIR","__namespace__","T_NS_C","exit","T_EXIT","die","function","T_FUNCTION","const","T_CONST","return","T_RETURN","try","T_TRY","catch","T_CATCH","finally","T_FINALLY","throw","T_THROW","if","T_IF","elseif","T_ELSEIF","endif","T_ENDIF","else","T_ELSE","while","T_WHILE","endwhile","T_ENDWHILE","do","T_DO","for","T_FOR","endfor","T_ENDFOR","foreach","T_FOREACH","endforeach","T_ENDFOREACH","declare","T_DECLARE","enddeclare","T_ENDDECLARE","instanceof","T_INSTANCEOF","T_AS","switch","T_SWITCH","endswitch","T_ENDSWITCH","case","T_CASE","default","T_DEFAULT","break","T_BREAK","continue","T_CONTINUE","goto","T_GOTO","echo","T_ECHO","print","T_PRINT","class","T_CLASS","interface","T_INTERFACE","T_TRAIT","T_EXTENDS","T_IMPLEMENTS","new","T_NEW","clone","T_CLONE","var","T_VAR","eval","T_EVAL","include","T_INCLUDE","include_once","T_INCLUDE_ONCE","T_REQUIRE","require_once","T_REQUIRE_ONCE","namespace","T_NAMESPACE","use","T_USE","insteadof","T_INSTEADOF","global","T_GLOBAL","isset","T_ISSET","empty","T_EMPTY","__halt_compiler","T_HALT_COMPILER","static","T_STATIC","abstract","T_ABSTRACT","final","T_FINAL","private","T_PRIVATE","protected","T_PROTECTED","public","T_PUBLIC","unset","T_UNSET","T_LIST","T_ARRAY","callable","T_CALLABLE","or","T_LOGICAL_OR","and","T_LOGICAL_AND","xor","T_LOGICAL_XOR","castKeywords","int","T_INT_CAST","integer","real","T_DOUBLE_CAST","double","float","string","T_STRING_CAST","binary","T_ARRAY_CAST","object","T_OBJECT_CAST","bool","T_BOOL_CAST","boolean","T_UNSET_CAST","setInput","input","size","yylineno","yytext","last_line","last_column","conditionStack","done","begin","ch","unput","c","tryMatch","text","ahead","tryMatchCaseless","consume","getState","setState","state","appendToken","lex","next","T_WHITESPACE","T_COMMENT","T_DOC_COMMENT","T_OPEN_TAG","T_OPEN_TAG_WITH_ECHO","condition","curCondition","stateCb","popState","pop","tName","values","console","log","stack","k","./lexer/comments.js","./lexer/initial.js","./lexer/numbers.js","./lexer/property.js","./lexer/scripting.js","./lexer/strings.js","./lexer/tokens.js","./lexer/utils.js","92","aspTagMode","is_WHITESPACE","93","nextINITIAL","matchINITIAL","T_INLINE_HTML","94","arch","MAX_LENGTH_OF_LONG","long_min_digits","consume_NUM","hasPoint","is_HEX","consume_HNUM","consume_BNUM","is_NUM","consume_LNUM","T_DNUMBER","T_LNUMBER","_process","95","matchST_LOOKING_FOR_PROPERTY","T_OBJECT_OPERATOR","is_LABEL_START","consume_LABEL","T_STRING","matchST_LOOKING_FOR_VARNAME","T_STRING_VARNAME","matchST_VAR_OFFSET","T_NUM_STRING","T_VARIABLE","T_ENCAPSED_AND_WHITESPACE","is_TOKEN","96","matchST_IN_SCRIPTING","consume_TOKEN","T_CONSTANT_ENCAPSED_STRING","ST_DOUBLE_QUOTES","nextCH","T_CLOSE_TAG","97","is_HEREDOC","revert","is_TABSPACE","tChar","yyoffset","is_LABEL","yylabel","heredoc_label","T_START_HEREDOC","prefix","isDOC_MATCH","matchST_NOWDOC","T_END_HEREDOC","matchST_HEREDOC","T_DOLLAR_OPEN_CURLY_BRACES","consume_VARIABLE","T_CURLY_OPEN","matchST_BACKQUOTE","matchST_DOUBLE_QUOTES","98","id","T_YIELD_FROM","T_YIELD","tokenTerminals","$","-","nchar","T_DEC","T_MINUS_EQUAL","\\","T_NS_SEPARATOR","/","T_DIV_EQUAL",":","T_DOUBLE_COLON","(","initial","consume_TABSPACE","yylen","castToken","castId","=","T_DOUBLE_ARROW","T_IS_IDENTICAL","T_IS_EQUAL","+","T_INC","T_PLUS_EQUAL","!","T_IS_NOT_IDENTICAL","T_IS_NOT_EQUAL","?","T_COALESCE","<","T_SL_EQUAL","T_SL","T_SPACESHIP","T_IS_SMALLER_OR_EQUAL",">","T_IS_GREATER_OR_EQUAL","T_SR_EQUAL","T_SR","*","T_MUL_EQUAL","T_POW_EQUAL","T_POW",".","T_CONCAT_EQUAL","T_ELLIPSIS","%","T_MOD_EQUAL","&","T_AND_EQUAL","T_BOOLEAN_AND","|","T_OR_EQUAL","T_BOOLEAN_OR","^","T_XOR_EQUAL","99","charCodeAt","indexOf","100","isNumber","isNaN","parseFloat","isFinite","ast","prev","extractDoc","suppressErrors","entries","VARIABLE","SCALAR","T_MAGIC_CONST","T_MEMBER_FLAGS","EOS","EXPR","getTokenName","parse","filename","_errors","currentNamespace","innerList","program","childs","nextWithComments","read_start","undefined","isArray","raiseError","msgExpect","expect","err","SyntaxError","lineNumber","fileName","columnNumber","error","msg","symbol","expectEndOfStatement","ignoreStack","showlog","split","trim","found","ignoreComments","is","./parser/array.js","./parser/class.js","./parser/comment.js","./parser/expr.js","./parser/function.js","./parser/if.js","./parser/loops.js","./parser/main.js","./parser/namespace.js","./parser/scalar.js","./parser/statement.js","./parser/switch.js","./parser/try.js","./parser/utils.js","./parser/variable.js","101","ArrayExpr","ArrayEntry","read_array","read_array_pair_list","read_variable","read_expr","read_dim_offset","102","read_class","flag","propName","propExtends","propImplements","read_namespace_name","read_name_list","read_class_body","read_class_scope","read_member_flags","variables","read_variable_list","read_function","constants","read_constant_list","read_trait_use_statement","read_doc_comment","read_comment","read_list","read_variable_declaration","read_constant_declaration","asInterface","idx","val","read_interface","read_interface_body","read_function_declaration","read_trait","read_trait_use_alias","103","docSplit","104","read_expr_item","trueArg","recursive_variable_chain_scan","read_dereferencable","read_function_argument_list","read_encapsed_string","assign","isInner","assignList","read_assignment_list","hasItem","read_new_expr","arg","backup","isConst","read_scalar","read_class_name_reference","read_static_getter","read_assignment_list_element","105","is_reference","is_variadic","closure","read_code_block","nodeName","returnType","params","read_parameter_list","read_lexical_var","read_type","read_parameter","wasVariadic","argument","read_argument_list","106","read_if","read_if_expr","read_elseif_short","read_else_short","read_inner_statement","read_statement","107","read_while","read_short_form","read_do","read_for","read_foreach","read_foreach_variable","108","read_namespace","read_top_statement","109","read_top_statements","relative","read_use_statement","read_use_type","read_use_declaration","read_use_declarations","typed","read_use_alias","useitem","110","specialChar","\\r","\\n","\\t","\\v","fromCharCode","\\e","\\f","\\\\","\\$","\\\"","\\'","resolve_special_chars","replace","seq","get_magic_constant","lastCh","read_encapsed_string_item","varName","read_simple_variable","read_encaps_var_offset","encapsed","111","statement","read_const_list","read_inner_statements","read_declare_list","read_switch","current","read_variable_declarations","read_try","top","112","read_switch_case_list","read_case_list","stopToken","113","item","114","separator","preserveFirstSeparator","115","read_only","read_reference_variable","literal","recursive_scan_loop","isDblQuote","num","116","117","118","119","120","121","122","123","124","125","126","127","128","129","130","131","132","133","134","135","136","137","138","139","140","141","142","143","144","145","146","147","148","149","150","151","152","153","154","155","156","157","158","159","160","161","162","163","164","165","166","167","168","169","170","171","172","173","174","175","176","177","178","179","180","181","182","183","184","185","186","187","188","189","190","191","192","193","194","195","196","197","198","199","200","201","202","203","204","205","206","207","208","209","210","211","212","213","214","215","216","217","218","219","220","221","222","223","224","225","226","227","228","229","230","231","232","233","php-parser","combine","to","keys","bind","options","parseEval","parseCode","tokenGetAll","entry","hasOwnProperty","./ast","./lexer","./parser","./tokens"],"mappings":"AAEAA,QAAQ,QAAUC,GAAEC,EAAEC,EAAEC,GAAG,QAASC,GAAEC,EAAEC,GAAG,IAAIJ,EAAEG,GAAG,CAAC,IAAIJ,EAAEI,GAAG,CAAC,GAAIE,GAAkB,kBAATR,UAAqBA,OAAQ,KAAIO,GAAGC,EAAE,MAAOA,GAAEF,GAAE,EAAI,IAAGG,EAAE,MAAOA,GAAEH,GAAE,EAAI,IAAII,GAAE,GAAIC,OAAM,uBAAuBL,EAAE,IAAK,MAAMI,GAAEE,KAAK,mBAAmBF,EAAE,GAAIG,GAAEV,EAAEG,IAAIQ,WAAYZ,GAAEI,GAAG,GAAGS,KAAKF,EAAEC,QAAQ,SAASb,GAAG,GAAIE,GAAED,EAAEI,GAAG,GAAGL,EAAG,OAAOI,GAAEF,EAAEA,EAAEF,IAAIY,EAAEA,EAAEC,QAAQb,EAAEC,EAAEC,EAAEC,GAAG,MAAOD,GAAEG,GAAGQ,QAAkD,IAAI,GAA1CL,GAAkB,kBAATT,UAAqBA,QAAgBM,EAAE,EAAEA,EAAEF,EAAEY,OAAOV,IAAID,EAAED,EAAEE,GAAI,OAAOD,KAAKY,GAAG,SAASjB,QAAQkB,OAAOJ,SAY/d,QAASK,oBACL,KAAM,IAAIR,OAAM,mCAEpB,QAASS,uBACL,KAAM,IAAIT,OAAM,qCAsBpB,QAASU,YAAWC,KAChB,GAAIC,mBAAqBC,WAErB,MAAOA,YAAWF,IAAK,EAG3B,KAAKC,mBAAqBJ,mBAAqBI,mBAAqBC,WAEhE,MADAD,kBAAmBC,WACZA,WAAWF,IAAK,EAE3B,KAEI,MAAOC,kBAAiBD,IAAK,GAC/B,MAAMrB,GACJ,IAEI,MAAOsB,kBAAiBR,KAAK,KAAMO,IAAK,GAC1C,MAAMrB,GAEJ,MAAOsB,kBAAiBR,KAAKU,KAAMH,IAAK,KAMpD,QAASI,iBAAgBC;AACrB,GAAIC,qBAAuBC,aAEvB,MAAOA,cAAaF,OAGxB,KAAKC,qBAAuBR,sBAAwBQ,qBAAuBC,aAEvE,MADAD,oBAAqBC,aACdA,aAAaF,OAExB,KAEI,MAAOC,oBAAmBD,QAC5B,MAAO1B,GACL,IAEI,MAAO2B,oBAAmBb,KAAK,KAAMY,QACvC,MAAO1B,GAGL,MAAO2B,oBAAmBb,KAAKU,KAAME,UAYjD,QAASG,mBACAC,UAAaC,eAGlBD,UAAW,EACPC,aAAahB,OACbiB,MAAQD,aAAaE,OAAOD,OAE5BE,YAAa,EAEbF,MAAMjB,QACNoB,cAIR,QAASA,cACL,IAAIL,SAAJ,CAGA,GAAIM,SAAUhB,WAAWS,gBACzBC,WAAW,CAGX,KADA,GAAIO,KAAML,MAAMjB,OACVsB,KAAK,CAGP,IAFAN,aAAeC,MACfA,WACSE,WAAaG,KACdN,cACAA,aAAaG,YAAYI,KAGjCJ,aAAa,EACbG,IAAML,MAAMjB,OAEhBgB,aAAe,KACfD,UAAW,EACXL,gBAAgBW,UAiBpB,QAASG,MAAKlB,IAAKmB,OACfhB,KAAKH,IAAMA,IACXG,KAAKgB,MAAQA,MAYjB,QAASC,SAhKT,GAOInB,kBACAK,mBARAe,QAAUzB,OAAOJ,YAgBpB,WACG,IAEQS,iBADsB,kBAAfC,YACYA,WAEAL;CAEzB,MAAOlB,GACLsB,iBAAmBJ,iBAEvB,IAEQS,mBADwB,kBAAjBC,cACcA,aAEAT,oBAE3B,MAAOnB,GACL2B,mBAAqBR,uBAuD7B,IAEIY,cAFAC,SACAF,UAAW,EAEXI,YAAa,CAyCjBQ,SAAQC,SAAW,SAAUtB,KACzB,GAAIuB,MAAO,GAAIC,OAAMC,UAAU/B,OAAS,EACxC,IAAI+B,UAAU/B,OAAS,EACnB,IAAK,GAAIP,GAAI,EAAGA,EAAIsC,UAAU/B,OAAQP,IAClCoC,KAAKpC,EAAI,GAAKsC,UAAUtC,EAGhCwB,OAAMe,KAAK,GAAIR,MAAKlB,IAAKuB,OACJ,IAAjBZ,MAAMjB,QAAiBe,UACvBV,WAAWe,aASnBI,KAAKS,UAAUV,IAAM,WACjBd,KAAKH,IAAI4B,MAAM,KAAMzB,KAAKgB,QAE9BE,QAAQQ,MAAQ,UAChBR,QAAQS,SAAU,EAClBT,QAAQU,OACRV,QAAQW,QACRX,QAAQY,QAAU,GAClBZ,QAAQa,YAIRb,QAAQc,GAAKf,KACbC,QAAQe,YAAchB,KACtBC,QAAQgB,KAAOjB,KACfC,QAAQiB,IAAMlB,KACdC,QAAQkB,eAAiBnB,KACzBC,QAAQmB,mBAAqBpB,KAC7BC,QAAQoB,KAAOrB,KAEfC,QAAQqB,QAAU,SAAUC,MACxB,KAAM,IAAItD,OAAM,qCAGpBgC,QAAQuB,IAAM,WAAc,MAAO,KACnCvB,QAAQwB,MAAQ,SAAUC,KACtB,KAAM,IAAIzD,OAAM,mCAEpBgC,QAAQ0B,MAAQ,WAAa,MAAO;OAE9BC,GAAG,SAAStE,QAAQkB,OAAOJ,SAOjC,GAAIyD,UAAWvE,QAAQ,kBACnBwE,SAAWxE,QAAQ,kBAmGnByE,IAAM,SAASC,cAAeC,YAChClD,KAAKiD,cAAgBA,cACrBjD,KAAKkD,WAAaA,WAUpBF,KAAIxB,UAAU2B,SAAW,SAASC,QAChC,MAAO,IAAIL,UACTK,OAAOC,MAAMC,OAAOC,WACpBH,OAAOC,MAAMC,OAAOE,aACpBJ,OAAOC,MAAMC,OAAOG,eAMxBT,IAAIU,gBAED,OACA,QACA,QACA,MACA,MACA,OACA,OACA,OACA,MACA,MACA,MACA,KAAM,KAAM,MAAO,MAAmB,QACtC,IAAK,KAAM,IAAK,OAChB,KAAM,OACN,IAAK,IAAK,MACV,IAAK,IAAK,MACV,MACA,eAIDC,QAAQ,SAAUC,KAAMC,OACxBD,KAAKD,QAAQ,SAAUG,UACrBd,IAAIU,WAAWI,UAAYD,MAAQ,KAQvCb,KAAIxB,UAAUuC,kBAAoB,SAASC,QACzC,GAAIC,OAEJ,IAAoB,QAAhBD,OAAOE,MACT,GAAIF,OAAOG,MACT,GAA0B,QAAtBH,OAAOG,MAAMD,KAAgB,CAC/B,GAAIE,QAASpB,IAAIU,WAAWM,OAAOK,MAC/BC,OAAStB,IAAIU,WAAWM,OAAOG,MAAME,KACrCD,SAAUE,QAAUA,QAAUF,SAGhCH,OAASD,OAAOG,MAChBH,OAAOG,MAAQH,OAAOG,MAAMI,KAC5BN,OAAOM,KAAOvE,KAAK+D,kBAAkBC,QACrCA,OAASC;KAEN,IAA0B,UAAtBD,OAAOG,MAAMD,KAAkB,CACxC,GAAIE,QAASpB,IAAIU,WAAWM,OAAOK,MAC/BC,OAAStB,IAAIU,WAAW,IACxBU,SAAUE,QAAUA,QAAUF,SAChCH,OAASD,OAAOG,MAChBH,OAAOG,MAAQH,OAAOG,MAAMK,KAC5BP,OAAOO,KAAOxE,KAAK+D,kBAAkBC,QACrCA,OAASC,aAIV,IAAoB,UAAhBD,OAAOE,KAEZF,OAAOS,OAEgB,QAArBT,OAAOS,KAAKP,MACdD,OAASD,OAAOS,KAChBT,OAAOS,KAAOT,OAAOS,KAAKF,KAC1BN,OAAOM,KAAOvE,KAAK+D,kBAAkBC,QACrCA,OAASC,QACqB,UAArBD,OAAOS,KAAKP,OACrBD,OAASD,OAAOS,KAChBT,OAAOS,KAAOT,OAAOS,KAAKD,KAC1BP,OAAOO,KAAOxE,KAAK+D,kBAAkBC,QACrCA,OAASC,aAGR,IAAoB,UAAhBD,OAAOE,KAEZF,OAAOU,WAAuC,UAA1BV,OAAOU,UAAUR,OACvCD,OAASD,OAAOU,UAChBV,OAAOU,UAAYT,OAAOO,KAC1BP,OAAOO,KAAOxE,KAAK+D,kBAAkBC,QACrCA,OAASC,YAEN,IAAoB,WAAhBD,OAAOE,MAEZF,OAAOG,OAA+B,QAAtBH,OAAOG,MAAMD,KAAgB,CAC/C,GAAIE,QAASpB,IAAIU,WAAW,KACxBY,OAAStB,IAAIU,WAAWM,OAAOG,MAAME,KAErCD,SAAUE,QAAUA,OAASF,SAC/BH,OAASD,OAAOG,MAChBH,OAAOG,MAAQH,OAAOG,MAAMI,KAC5BN,OAAOM,KAAOP,OACdA,OAASC,QAIf,MAAOD;EAUThB,IAAIxB,UAAUmD,QAAU,SAAST,KAAMd,QACrC,GAAIwB,OAAQ,MACR5E,KAAKiD,eAAiBjD,KAAKkD,cAC7B0B,MAAQ5E,KAAKmD,SAASC,QAExB,IAAIyB,MAAO7E,IAEX,OAAO,YACL,GAAI8E,UAAW,KACX1D,KAAOC,MAAMG,UAAUuD,MAAMzF,KAAKgC,UACtC,IAAIuD,KAAK5B,eAAiB4B,KAAK3B,WAAY,CACzC,GAAI8B,KAAM,IACNH,MAAK3B,aACP8B,IAAM5B,OAAOC,MAAM4B,OAAOC,UACxBN,MAAMO,OACN/B,OAAOC,MAAMC,OAAO8B,cAItBN,SADED,KAAK5B,cACI,GAAIH,UAASkC,IAAKJ,MAAO,GAAI7B,UACtCK,OAAOC,MAAMC,OAAO+B,UACpBjC,OAAOC,MAAMC,OAAOgC,YACpBlC,OAAOC,MAAMC,OAAO8B,cAGX,GAAItC,UAASkC,IAAK,KAAM,MAGrC5D,KAAKG,KAAKuD,UAGPZ,OACHA,KAAO9C,KAAKmE,QAGd,IAAIC,MAAOX,KAAKX,KAChB,IAAoB,kBAATsB,MACT,KAAM,IAAItG,OAAM,mBAAmBgF,KAAK,IAE1C,IAAIF,QAASyB,OAAOC,OAAOF,KAAKhE,UAEhC,OADAgE,MAAK/D,MAAMuC,OAAQ5C,MACZyD,KAAKd,kBAAkBC,WAMhCzF,QAAQ,eACRA,QAAQ,gBACRA,QAAQ,aACRA,QAAQ,eACRA,QAAQ,iBACRA,QAAQ,eACRA,QAAQ,cACRA,QAAQ,cACRA,QAAQ,cACRA,QAAQ,eACRA,QAAQ,eACRA,QAAQ,uBACRA,QAAQ,eACRA,QAAQ,iBACRA,QAAQ,kBACRA,QAAQ,kBACRA,QAAQ,kBACRA,QAAQ,qBACRA,QAAQ,iBACRA,QAAQ,YACRA,QAAQ,aACRA,QAAQ,cACRA,QAAQ,eACRA,QAAQ,kBACRA,QAAQ,eACRA,QAAQ,eACRA,QAAQ,cACRA,QAAQ,cACRA,QAAQ,oBACRA,QAAQ,aACRA,QAAQ,iBACRA,QAAQ,kBACRA,QAAQ,gBACRA,QAAQ,cACRA,QAAQ,cACRA,QAAQ,oBACRA,QAAQ,YACRA,QAAQ,iBACRA,QAAQ,gBACRA,QAAQ,mBACRA,QAAQ,eACRA,QAAQ,eACRA,QAAQ,cACRA,QAAQ,iBACRA,QAAQ,gBACRA,QAAQ,eACRA,QAAQ,gBACRA,QAAQ,mBACRA,QAAQ,aACRA,QAAQ,cACRA,QAAQ,gBACRA,QAAQ,gBACRA,QAAQ,sBACRA,QAAQ,mBACRA,QAAQ,mBACRA,QAAQ,qBACRA,QAAQ,cACRA,QAAQ,aACRA,QAAQ,eACRA,QAAQ,iBACRA,QAAQ,kBACRA,QAAQ,wBACRA,QAAQ,eACRA,QAAQ,gBACRA,QAAQ,gBACRA,QAAQ,mBACRA,QAAQ,gBACRA,QAAQ,sBACRA,QAAQ,gBACRA,QAAQ,gBACRA,QAAQ,aACRA,QAAQ,eACRA,QAAQ,eACRA,QAAQ,oBACRA,QAAQ,yBACRA,QAAQ,kBACRA,QAAQ,aACRA,QAAQ,eACRA,QAAQ,eACRA,QAAQ,kBACRA,QAAQ,iBACRA,QAAQ,kBACRA,QAAQ,kBACRA,QAAQ,eACRA,QAAQ,eACRA,QAAQ,oBACRoF,QAAQ,SAAUgC;AAClB,GAAIzB,MAAOyB,KAAKnE,UAAUoE,YAAYpD,KAAKqD,aAC3B,OAAZ3B,KAAK,KAAYA,KAAOA,KAAKgB,UAAU,IAC3ClC,IAAIxB,UAAU0C,MAAQyB,OAGxBlG,OAAOJ,QAAU2D,MAEd8C,cAAc,EAAEC,eAAe,EAAEC,YAAY,EAAEC,cAAc,EAAEC,gBAAgB,EAAEC,cAAc,EAAEC,aAAa,EAAEC,aAAa,GAAGC,aAAa,GAAGC,cAAc,GAAGC,cAAc,GAAGC,sBAAsB,GAAGC,cAAc,GAAGC,gBAAgB,GAAGC,iBAAiB,GAAGC,iBAAiB,GAAGC,iBAAiB,GAAGC,oBAAoB,GAAGC,gBAAgB,GAAGC,WAAW,GAAGC,YAAY,GAAGC,aAAa,GAAGC,cAAc,GAAGC,iBAAiB,GAAGC,cAAc,GAAGC,cAAc,GAAGC,aAAa,GAAGC,aAAa,GAAGC,mBAAmB,GAAGC,YAAY,GAAGC,gBAAgB,GAAGC,iBAAiB,GAAGC,eAAe,GAAGC,aAAa,GAAGC,aAAa,GAAGC,mBAAmB,GAAGC,WAAW,GAAGC,gBAAgB,GAAGC,eAAe,GAAGC,kBAAkB,GAAGC,cAAc,GAAGC,cAAc,GAAGC,aAAa,GAAGC,gBAAgB,GAAGC,iBAAiB,GAAGC,eAAe,GAAGC,cAAc,GAAGC,eAAe,GAAGC,kBAAkB,GAAGC,YAAY;AAAGC,aAAa,GAAGC,eAAe,GAAGC,eAAe,GAAGC,qBAAqB,GAAGC,kBAAkB,GAAGC,kBAAkB,GAAGC,oBAAoB,GAAGC,iBAAiB,GAAGC,aAAa,GAAGC,YAAY,GAAGC,cAAc,GAAGC,gBAAgB,GAAGC,iBAAiB,GAAGC,uBAAuB,GAAGC,cAAc,GAAGC,eAAe,GAAGC,eAAe,GAAGC,kBAAkB,GAAGC,eAAe,GAAGC,qBAAqB,GAAGC,eAAe,GAAGC,eAAe,GAAGC,YAAY,GAAGC,cAAc,GAAGC,cAAc,GAAGC,mBAAmB,GAAGC,wBAAwB,GAAGC,iBAAiB,GAAGC,YAAY,GAAGC,cAAc,GAAGC,cAAc,GAAGC,iBAAiB,GAAGC,gBAAgB,GAAGC,iBAAiB,GAAGC,iBAAiB,GAAGC,cAAc,GAAGC,cAAc,GAAGC,kBAAkB,KAAKC,GAAG,SAAS/M,QAAQkB,OAAOJ,SAO9mD,GAAIkM,MAAOhN,QAAQ,gBACfiN,KAAO,QA+BPnK,MAAQkK,KAAKE,QAAQ,QAASpK,OAAMqK,UAAWC,MAAO7G,UACxDyG,KAAK9J,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAK2L,MAAQA,MACb3L,KAAK0L,UAAYA,WAGnBjM,QAAOJ,QAAUgC,QAEduK,eAAe,KAAKC,GAAG,SAAStN,QAAQkB,OAAOJ;AAOlD,GAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,SAUPO,OAASD,UAAUL,QAAQ,QAASM,QAAOxH,KAAMJ,MAAOL,SAAUgB,UACpEgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAK8D,SAAWA,SAChB9D,KAAKuE,KAAOA,KACZvE,KAAKmE,MAAQA,OAGf1E,QAAOJ,QAAU0M,SAEdC,cAAc,KAAKC,GAAG,SAAS1N,QAAQkB,OAAOJ,SAMjD,YAEA,IAAI6M,WAAY3N,QAAQ,eACpBiN,KAAO,MASPW,IAAMD,UAAUT,QAAQ,QAASU,KAAI9H,KAAME,KAAMJ,MAAOW,UAC1DoH,UAAUzK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKqE,KAAOA,KACZrE,KAAKuE,KAAOA,KACZvE,KAAKmE,MAAQA,OAGf1E,QAAOJ,QAAU8M,MAEdC,cAAc,KAAKC,GAAG,SAAS9N,QAAQkB,OAAOJ,SAOjD,GAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,QAQPc,MAAQR,UAAUL,QAAQ,QAASa,OAAMpI,KAAMqI,SAAUzH,UAC3DgH,UAAUrK,MAAMzB,MAAOkE,MAAQsH,KAAM1G,WACrC9E,KAAKuM,SAAWA,UAGlB9M,QAAOJ,QAAUiN,QAEdN,cAAc,KAAKQ,GAAG,SAASjO,QAAQkB,OAAOJ,SAOjD,GAAIoN,SAAUlO,QAAQ,aAClBiN,KAAO,UAOPkB,QAAUD,QAAQhB,QAAQ,QAASiB,SAAQC,MAAO7H,UACpD2H,QAAQhL,MAAMzB,MAAOwL,KAAMmB,MAAO7H,YAGpCrF,QAAOJ,QAAUqN,UAEdE,YAAY;GAAKC,GAAG,SAAStO,QAAQkB,OAAOJ,SAM/C,YACA,IAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,QAQPuB,MAAQD,KAAKrB,QAAQ,QAASsB,OAAMC,MAAOlI,UAC7CgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAKgN,MAAQA,OAGfvN,QAAOJ,QAAU0N,QAEdE,SAAS,KAAKC,GAAG,SAAS3O,QAAQkB,OAAOJ,SAM5C,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,OASP2B,KAAOrB,UAAUL,QAAQ,QAAS0B,MAAK1I,KAAMrD,KAAM0D,UACrDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKyE,KAAOA,KACZzE,KAAKsB,UAAYF,MAGnB3B,QAAOJ,QAAU8N,OAEdnB,cAAc,KAAKoB,IAAI,SAAS7O,QAAQkB,OAAOJ,SAMlD,YACA,IAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,OASP6B,KAAOP,KAAKrB,QAAQ,QAAS4B,MAAK7I,KAAM8I,KAAMxI,UAChDgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAKwE,KAAOA,KACZxE,KAAKsN,KAAOA,MAGd7N,QAAOJ,QAAUgO,OAEdJ,SAAS,KAAKM,IAAI,SAAShP,QAAQkB,OAAOJ,SAM7C,YAEA,IAAI6M,WAAY3N,QAAQ,eACpBiN,KAAO,OASPgC,KAAOtB,UAAUT,QAAQ,QAAS+B,MAAKnJ,KAAMI,KAAMK,UACrDoH,UAAUzK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKqE,KAAOA,KACZrE,KAAKyE,KAAOA,MAGdhF,QAAOJ,QAAUmO,OAEdpB,cAAc,KAAKqB,IAAI,SAASlP,QAAQkB,OAAOJ;AAMlD,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,QAWPkC,MAAQ5B,UAAUL,QAAQ,QAASiC,OAAMJ,KAAM7I,KAAMkJ,SAAU7I,UACjEgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKsN,KAAOA,KACZtN,KAAKyE,KAAOA,KACZzE,KAAK2N,SAAWA,UAGlBlO,QAAOJ,QAAUqO,QAEd1B,cAAc,KAAK4B,IAAI,SAASrP,QAAQkB,OAAOJ,SAOlD,GAAIwO,aAActP,QAAQ,iBACtBiN,KAAO,QAcPsC,MAAQD,YAAYpC,QAAQ,QAASqC,OAAMtL,KAAMuL,IAAKC,KAAMV,KAAMW,MAAOnJ,UAC3E+I,YAAYpM,MAAMzB,MAAOwL,KAAMhJ,KAAMsC,WACrC9E,KAAKkO,aAAc1L,KACnBxC,KAAKyL,QAAUsC,IACf/N,KAAKmO,WAAaH,KAClBhO,KAAKsN,KAAOA,KACZtN,KAAKoO,WAAWH,QAGlBxO,QAAOJ,QAAUyO,QAEdO,gBAAgB,KAAKC,IAAI,SAAS/P,QAAQkB,OAAOJ,SAOpD,GAAIkP,UAAWhQ,QAAQ,cACnBiN,KAAO,gBASPgD,cAAgBD,SAAS9C,QAAQ,QAAS+C,eAAchM,KAAMmK,MAAOsB,MAAOnJ,UAC9EyJ,SAAS9M,MAAMzB,MAAOwC,KAAMmK,MAAO7H,WACnC9E,KAAKkE,KAAOsH,KACZxL,KAAKoO,WAAWH,QAGlBxO,QAAOJ,QAAUmP,gBAEdC,aAAa,KAAKC,IAAI,SAASnQ,QAAQkB,OAAOJ,SAOjD,GAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,QAQPmD,MAAQ7C,UAAUL,QAAQ,QAASkD,OAAMlK,KAAMK;AACjDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKyE,KAAOA,MAGdhF,QAAOJ,QAAUsP,QAEd3C,cAAc,KAAK4C,IAAI,SAASrQ,QAAQkB,OAAOJ,SAMlD,YACA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,UAcPqD,QAAU/C,UAAUL,QAAQ,QAASoD,SAAQzN,KAAM0N,MAAOC,KAAM1K,KAAM2K,SAAUC,SAAUnK,UAC5FgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAK+O,KAAOA,KACZ/O,KAAKsB,UAAYF,KACjBpB,KAAK8O,MAAQA,MACb9O,KAAKqE,KAAOA,KACZrE,KAAKgP,SAAWA,SAChBhP,KAAKiP,SAAWA,WAAY,EAC5BjP,KAAKsN,KAAO,MAGd7N,QAAOJ,QAAUwP,UAEd7C,cAAc,KAAKkD,IAAI,SAAS3Q,QAAQkB,OAAOJ,SAOlD,GAAIwO,aAActP,QAAQ,iBACtBiN,KAAO,WAQP+C,SAAWV,YAAYpC,QAAQ,QAAS8C,UAAS/L,KAAMmK,MAAO7H,UAChE+I,YAAYpM,MAAMzB,MAAOwL,KAAMhJ,KAAMsC,WACrC9E,KAAK2M,MAAQA,OAGflN,QAAOJ,QAAUkP,WAEdF,gBAAgB,KAAKc,IAAI,SAAS5Q,QAAQkB,OAAOJ,SAOpD,GAAIkM,MAAOhN,QAAQ,gBACfiN,KAAO,WAQP4D,SAAW7D,KAAKE,QAAQ,QAAS2D,UAASC,WAAYvK,UACxDyG,KAAK9J,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAKwC,KAAO6M,YAGd5P,QAAOJ,QAAU+P,WAEdxD,eAAe;GAAK0D,IAAI,SAAS/Q,QAAQkB,OAAOJ,SAMnD,YACA,IAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,WAQP+D,SAAWzC,KAAKrB,QAAQ,QAAS8D,UAASvC,MAAOlI,UACnDgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAKgN,MAAQA,OAGfvN,QAAOJ,QAAUkQ,WAEdtC,SAAS,KAAKuC,IAAI,SAASjR,QAAQkB,OAAOJ,SAO7C,GAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,cAEPiE,UAAgB,SAChBC,aAAgB,YAChBC,WAAgB,UAQhB9B,YAAc/B,UAAUL,QAAQ,QAASoC,aAAY3J,KAAM1B,KAAMsC,UACnEgH,UAAUrK,MAAMzB,MAAOkE,MAAQsH,KAAM1G,WACrC9E,KAAKwC,KAAOA,MAQdqL,aAAYrM,UAAU4M,WAAa,SAASH,OAC1CjO,KAAK4P,WAA0B,IAAb3B,MAAM,GACxBjO,KAAK6P,QAAuB,IAAb5B,MAAM,GACH,UAAdjO,KAAKkE,OACU,IAAb+J,MAAM,GACRjO,KAAK8P,WAAaL,UACI,IAAbxB,MAAM,GACfjO,KAAK8P,WAAaJ,aACI,IAAbzB,MAAM,KACfjO,KAAK8P,WAAaH,YAEpB3P,KAAKiP,SAAwB,IAAbhB,MAAM,KAI1BxO,OAAOJ,QAAUwO,cAEd7B,cAAc,KAAK+D,IAAI,SAASxR,QAAQkB,OAAOJ,SAOlD,GAAIiN,OAAQ/N,QAAQ,WAChBiN,KAAO,UAUPwE,QAAU1D,MAAMb,QAAQ,QAASuE,SAAQvL,KAAM6I,KAAM2C,KAAMnL,UAC7DwH,MAAM7K,MAAMzB,MAAOwL,KAAM8B,KAAMxI;AAC/B9E,KAAKyE,KAAOA,KACZzE,KAAKiQ,KAAOA,MAcdD,SAAQE,WAAa,QAYrBF,QAAQG,WAAa,QAerBH,QAAQI,UAAY,OAEpB3Q,OAAOJ,QAAU2Q,UAEdK,UAAU,IAAIC,IAAI,SAAS/R,QAAQkB,OAAOJ,SAM7C,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,KASP+E,GAAKzE,UAAUL,QAAQ,QAAS8E,IAAG/L,KAAM8I,KAAMxI,UACjDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKwE,KAAOA,KACZxE,KAAKsN,KAAOA,MAGd7N,QAAOJ,QAAUkR,KAEdvE,cAAc,KAAKwE,IAAI,SAASjS,QAAQkB,OAAOJ,SAOlD,GAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,MASPiF,IAAM3D,KAAKrB,QAAQ,QAASgF,KAAIC,MAAOC,MAAO7L,UAChDgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAK0Q,MAAQA,MACb1Q,KAAK2Q,MAAQA,OAGflR,QAAOJ,QAAUoR,MAEdxD,SAAS,KAAK2D,IAAI,SAASrS,QAAQkB,OAAOJ,SAO7C,GAAIwR,KAAMtS,QAAQ,SACdiN,KAAO,OAOPsF,KAAOD,IAAIpF,QAAQ,QAASqF,MAAK1P,KAAM0D,UACzC+L,IAAIpP,MAAMzB,MAAOwL,KAAMpK,KAAM0D,YAG/BrF,QAAOJ,QAAUyR,OAEdC,QAAQ,KAAKC,IAAI,SAASzS,QAAQkB,OAAOJ,SAO5C,GAAIwR,KAAMtS,QAAQ,SACdiN,KAAO,QAOPyF,MAAQJ,IAAIpF,QAAQ,QAASwF,OAAM7P,KAAM0D,UAC3C+L,IAAIpP,MAAMzB,MAAOwL,KAAMpK,KAAM0D,YAG/BrF,QAAOJ,QAAU4R,QAEdF,QAAQ;GAAKG,IAAI,SAAS3S,QAAQkB,OAAOJ,SAO5C,GAAIoN,SAAUlO,QAAQ,aAClBiN,KAAO,WASP2F,SAAW1E,QAAQhB,QAAQ,QAAS0F,UAASxE,MAAOtI,KAAMS,UAC5D2H,QAAQhL,MAAMzB,MAAOwL,KAAMmB,MAAO7H,WAClC9E,KAAKqE,KAAOA,MAYd8M,UAASC,YAAc,SAUvBD,SAASE,WAAa,QAatBF,SAASG,aAAe,UAUxBH,SAASI,YAAc,SAGvB9R,OAAOJ,QAAU8R,WAEdvE,YAAY,KAAK4E,IAAI,SAASjT,QAAQkB,OAAOJ,SAOhD,GAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,QASPiG,MAAQ3E,KAAKrB,QAAQ,QAASgG,OAAMC,IAAK/E,MAAO7H,UAClDgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAK0R,IAAMA,IACX1R,KAAK2M,MAAQA,OAGflN,QAAOJ,QAAUoS,QAEdxE,SAAS,KAAK0E,IAAI,SAASpT,QAAQkB,OAAOJ,SAO7C,GAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,QAYPtM,MAAQ4N,KAAKrB,QAAQ,QAASvM,OAAM0S,QAASC,MAAOC,KAAMC,SAAUjN,UACtEgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAK4R,QAAUA,QACf5R,KAAK6R,MAAQA,MACb7R,KAAK8R,KAAOA,KACZ9R,KAAK+R,SAAWA,UAGlBtS,QAAOJ,QAAUH,QAEd+N,SAAS,KAAK+E,IAAI,SAASzT,QAAQkB,OAAOJ,SAO7C,GAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,OAQPyG,KAAOnG,UAAUL,QAAQ,QAASwG,MAAKC,OAAQpN;AACjDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKkS,OAASA,QAGhBzS,QAAOJ,QAAU4S,OAEdjG,cAAc,KAAKmG,IAAI,SAAS5T,QAAQkB,OAAOJ,SAOlD,GAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,OAQP4G,KAAOtG,UAAUL,QAAQ,QAAS2G,MAAKC,OAAQvN,UACjDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKqS,OAASA,QAGhB5S,QAAOJ,QAAU+S,OAEdpG,cAAc,KAAKsG,IAAI,SAAS/T,QAAQkB,OAAOJ,SAOlD,GAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,aAQP+G,WAAazF,KAAKrB,QAAQ,QAAS8G,YAAWrO,KAAMY,UACtDgI,KAAKrL,MAAMzB,MAAOkE,MAAQsH,KAAM1G,YAGlCrF,QAAOJ,QAAUkT,aAEdtF,SAAS,KAAKuF,IAAI,SAASjU,QAAQkB,OAAOJ,SAM7C,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,MAaPiH,IAAM3G,UAAUL,QAAQ,QAASgH,KAAIC,KAAMlO,KAAMmO,UAAWrF,KAAM5B,UAAW5G,UAC/EgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAK0S,KAAOA,KACZ1S,KAAKwE,KAAOA,KACZxE,KAAK2S,UAAYA,UACjB3S,KAAK0L,UAAYA,UACjB1L,KAAKsN,KAAOA,MAGd7N,QAAOJ,QAAUoT,MAEdzG,cAAc,KAAK4G,IAAI,SAASrU,QAAQkB,OAAOJ,SAMlD,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,UAaPqH,QAAU/G,UAAUL,QAAQ,QAASoH,SAAQX,OAAQR,IAAK/E,MAAOW,KAAM5B,UAAW5G;AACpFgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKkS,OAASA,OACdlS,KAAK0R,IAAMA,IACX1R,KAAK2M,MAAQA,MACb3M,KAAK0L,UAAYA,UACjB1L,KAAKsN,KAAOA,MAGd7N,QAAOJ,QAAUwT,UAEd7G,cAAc,KAAK8G,IAAI,SAASvU,QAAQkB,OAAOJ,SAOlD,GAAIwO,aAActP,QAAQ,iBACtBiN,KAAgB,WAYhBuH,GAAKlF,YAAYpC,QAAQ,QAASuH,WAAUxQ,KAAMpB,KAAM0N,MAAOzK,KAAM2K,SAAUlK,UACjF+I,YAAYpM,MAAMzB,MAAOwL,KAAMhJ,KAAMsC,WACrC9E,KAAKsB,UAAYF,KACjBpB,KAAK8O,MAAQA,MACb9O,KAAKqE,KAAOA,KACZrE,KAAKgP,SAAWA,SAChBhP,KAAKsN,KAAO,MAEd7N,QAAOJ,QAAU0T,KAEd1E,gBAAgB,KAAK4E,IAAI,SAAS1U,QAAQkB,OAAOJ,SAMpD,YACA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,SAQP0H,OAASpH,UAAUL,QAAQ,QAASyH,QAAOvH,MAAO7G,UACpDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAK2L,MAAQA,OAGflM,QAAOJ,QAAU6T,SAEdlH,cAAc,KAAKmH,IAAI,SAAS5U,QAAQkB,OAAOJ,SAMlD,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,OASP4H,KAAOtH,UAAUL,QAAQ,QAAS2H,MAAKC,MAAOvO,UAChDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKqT,MAAQA,OAGf5T,QAAOJ,QAAU+T,OAEdpH,cAAc;GAAKsH,IAAI,SAAS/U,QAAQkB,OAAOJ,SAMlD,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,OASP+H,KAAOzH,UAAUL,QAAQ,QAAS8H,MAAKC,MAAO1O,UAChDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKwT,MAAQA,OAGf/T,QAAOJ,QAAUkU,OAEdvH,cAAc,KAAKyH,IAAI,SAASlV,QAAQkB,OAAOJ,SAOlD,GAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,aASPkI,WAAa5G,KAAKrB,QAAQ,QAASiI,YAAWlR,KAAMmR,WAAY7O,UAClEgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACpB6O,WACF3T,KAAK4T,WAAaF,WAAWG,cACJ,IAAhBrR,KAAKjD,OACdS,KAAK4T,WAAaF,WAAWI,iBACR,KAAZtR,KAAK,GACdxC,KAAK4T,WAAaF,WAAWK,oBAE7B/T,KAAK4T,WAAaF,WAAWM,eAE/BhU,KAAKwC,KAAOA,KAAKyR,KAAK,OAOxBP,YAAWI,iBAAmB,MAK9BJ,WAAWM,eAAiB,KAO5BN,WAAWK,oBAAsB,MAKjCL,WAAWG,cAAgB,KAG3BpU,OAAOJ,QAAUqU,aAEdzG,SAAS,KAAKiH,IAAI,SAAS3V,QAAQkB,OAAOJ,SAM7C,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,KAWP2I,GAAKrI,UAAUL,QAAQ,QAAS0I,IAAG3P,KAAM8I,KAAM8G,UAAW1I,UAAW5G,UACvEgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G;AAC7B9E,KAAKwE,KAAOA,KACZxE,KAAKsN,KAAOA,KACZtN,KAAKoU,UAAYA,UACjBpU,KAAK0L,UAAYA,WAGnBjM,QAAOJ,QAAU8U,KAEdnI,cAAc,KAAKqI,IAAI,SAAS9V,QAAQkB,OAAOJ,SAOlD,GAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,UAUP8I,QAAUxI,UAAUL,QAAQ,QAAS6I,SAAQpS,KAAM3D,QAASgW,OAAQzP,UACtEgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKkC,KAAOA,KACZlC,KAAKzB,QAAUA,QACfyB,KAAKuU,OAASA,QAGhB9U,QAAOJ,QAAUiV,UAEdtI,cAAc,KAAKwI,IAAI,SAASjW,QAAQkB,OAAOJ,SAOlD,GAAIoN,SAAUlO,QAAQ,aAClBiN,KAAO,SAOPiJ,OAAShI,QAAQhB,QAAQ,QAASgJ,QAAO9H,MAAO7H,UAClD2H,QAAQhL,MAAMzB,MAAOwL,KAAMmB,MAAO7H,YAGpCrF,QAAOJ,QAAUoV,SAEd7H,YAAY,KAAK8H,IAAI,SAASnW,QAAQkB,OAAOJ,SAOhD,GAAIwO,aAActP,QAAQ,iBACtBiN,KAAO,YAUPmJ,UAAY9G,YAAYpC,QAAQ,QAASkJ,WAAUnS,KAAMuL,IAAKT,KAAMxI,UACtE+I,YAAYpM,MAAMzB,MAAOwL,KAAMhJ,KAAMsC,WACrC9E,KAAKyL,QAAUsC,IACf/N,KAAKsN,KAAOA,MAGd7N,QAAOJ,QAAUsV,YAEdtG,gBAAgB,KAAKuG,IAAI,SAASrW,QAAQkB,OAAOJ,SAOpD,GAAIwR,KAAMtS,QAAQ,SACdiN,KAAO,QAOPqJ,MAAQhE,IAAIpF,QAAQ,QAASoJ,OAAMzT,KAAM0D;AAC3C+L,IAAIpP,MAAMzB,MAAOwL,KAAMpK,KAAM0D,YAG/BrF,QAAOJ,QAAUwV,QAEd9D,QAAQ,KAAK+D,IAAI,SAASvW,QAAQkB,OAAOJ,SAM5C,YACA,IAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,QAQPuJ,MAAQjI,KAAKrB,QAAQ,QAASsJ,OAAMvS,KAAMsC,UAC5CgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAKwC,KAAOA,MAGd/C,QAAOJ,QAAU0V,QAEd9H,SAAS,KAAK+H,IAAI,SAASzW,QAAQkB,OAAOJ,SAO7C,GAAIwR,KAAMtS,QAAQ,SACdiN,KAAO,OAOPyJ,KAAOpE,IAAIpF,QAAQ,QAASwJ,MAAK7T,KAAM0D,UACzC+L,IAAIpP,MAAMzB,MAAOwL,KAAMpK,KAAM0D,YAG/BrF,QAAOJ,QAAU4V,OAEdlE,QAAQ,KAAKmE,IAAI,SAAS3W,QAAQkB,OAAOJ,SAO5C,GAAIkM,MAAOhN,QAAQ,gBACfiN,KAAO,UAQPiB,QAAUlB,KAAKE,QAAQ,QAASgB,SAAQvI,KAAMyI,MAAO7H,UACvDyG,KAAK9J,MAAMzB,MAAOkE,MAAQsH,KAAM1G,WAChC9E,KAAK2M,MAAQA,OAGflN,QAAOJ,QAAUoN,UAEdb,eAAe,KAAKuJ,IAAI,SAAS5W,QAAQkB,OAAOJ,SAcnD,GAAIyD,UAAW,SAASoP,OAAQtN,MAAOwQ,KACrCpV,KAAKkS,OAASA,OACdlS,KAAK4E,MAAQA,MACb5E,KAAKoV,IAAMA,IAGb3V,QAAOJ,QAAUyD,cAEXuS,IAAI,SAAS9W,QAAQkB,OAAOJ,SAOlC,GAAIkM,MAAOhN,QAAQ,gBACfiN,KAAO,SASP8J,OAAS/J,KAAKE,QAAQ,QAAS6J,QAAOpR,KAAMO,KAAMU,OAAQL;AAC5DyG,KAAK9J,MAAMzB,MAAOkE,MAAQsH,KAAM1G,WAChC9E,KAAKyE,KAAOA,KACZzE,KAAKmF,OAASA,QAGhB1F,QAAOJ,QAAUiW,SAEd1J,eAAe,KAAK2J,IAAI,SAAShX,QAAQkB,OAAOJ,SAOnD,GAAIoN,SAAUlO,QAAQ,aAClBiN,KAAO,QAOPgK,MAAQ/I,QAAQhB,QAAQ,QAAS+J,OAAM7I,MAAO7H,UAChD2H,QAAQhL,MAAMzB,MAAOwL,KAAMmB,MAAO7H,YAGpCrF,QAAOJ,QAAUmW,QAEd5I,YAAY,KAAK6I,IAAI,SAASlX,QAAQkB,OAAOJ,SAOhD,GAAI0T,IAAKxU,QAAQ,cACbiN,KAAO,SAWPkK,OAAS3C,GAAGtH,QAAQ,QAASiK,UAC/B3C,GAAGtR,MAAMzB,KAAMsB,WACftB,KAAKkE,KAAOsH,MAGd/L,QAAOJ,QAAUqW,SAEdC,aAAa,KAAKC,IAAI,SAASrX,QAAQkB,OAAOJ,SAOjD,GAAIiN,OAAQ/N,QAAQ,WAEhBiN,MADajN,QAAQ,gBACd,aASPsX,UAAYvJ,MAAMb,QAAQ,QAASoK,WAAUrT,KAAM+J,SAAUuJ,aAAchR,UAC7EwH,MAAM7K,MAAMzB,MAAOwL,KAAMe,SAAUzH,WACnC9E,KAAKwC,KAAOA,KACZxC,KAAK8V,aAAeA,eAAgB,GAGtCrW,QAAOJ,QAAUwW,YAEdxF,UAAU,EAAE0F,eAAe,KAAKC,IAAI,SAASzX,QAAQkB,OAAOJ,SAM/D,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,MASPyK,IAAMnK,UAAUL,QAAQ,QAASwK,KAAIxR,KAAMrD,KAAM0D;AACnDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKyE,KAAOA,KACZzE,KAAKsB,UAAYF,MAGnB3B,QAAOJ,QAAU4W,MAEdjK,cAAc,KAAKkK,IAAI,SAAS3X,QAAQkB,OAAOJ,SAalD,GAAIyN,MAAO,QAASA,MAAK5I,KAAMY,UAC7B9E,KAAKkE,KAAOA,KACTY,WACD9E,KAAKmW,IAAMrR,UASfgI,MAAKrB,QAAU,SAAS7F,aAItB,MAHAA,aAAYpE,UAAYiE,OAAOC,OAAO1F,KAAKwB,WAC3CoE,YAAY6F,QAAUzL,KAAKyL,QAC3B7F,YAAYpE,UAAUoE,YAAcA,YAC7BA,aAGTnG,OAAOJ,QAAUyN,UAEXsJ,IAAI,SAAS7X,QAAQkB,OAAOJ,SAOlC,GAAIoN,SAAUlO,QAAQ,aAClBiN,KAAO,SASP6K,OAAS5J,QAAQhB,QAAQ,QAAS4K,QAAO1J,MAAO0G,MAAOvO,UACzD2H,QAAQhL,MAAMzB,MAAOwL,KAAMmB,MAAO7H,WAClC9E,KAAKqT,MAAQA,OAGf5T,QAAOJ,QAAUgX,SAEdzJ,YAAY,KAAK0J,IAAI,SAAS/X,QAAQkB,OAAOJ,SAOhD,GAAIoN,SAAUlO,QAAQ,aAClBiN,KAAO,SAOP+K,QAAU9J,QAAQhB,QAAQ,QAAS+K,QAAO7J,MAAO7H,UACnD2H,QAAQhL,MAAMzB,MAAOwL,KAAMmB,MAAO7H,YAGpCrF,QAAOJ,QAAUkX,UAEd3J,YAAY,KAAK6J,IAAI,SAASlY,QAAQkB,OAAOJ,SAMhD,YACA,IAAIiW,QAAS/W,QAAQ,YACjBiN,KAAO,eAOPkL,aAAepB,OAAO7J,QAAQ,QAASiL,cAAajS,KAAMU,OAAQL;AACpEwQ,OAAO7T,MAAMzB,MAAOwL,KAAM/G,KAAMU,OAAQL,YAG1CrF,QAAOJ,QAAUqX,eAEdC,WAAW,KAAKC,IAAI,SAASrY,QAAQkB,OAAOJ,SAM/C,YAEA,IAAIkM,MAAOhN,QAAQ,gBACfiN,KAAO,YAOPU,UAAYX,KAAKE,QAAQ,QAASS,WAAUhI,KAAMY,UACpDyG,KAAK9J,MAAMzB,MAAOkE,MAAQsH,KAAM1G,YAGlCrF,QAAOJ,QAAU6M,YAEdN,eAAe,KAAKiL,IAAI,SAAStY,QAAQkB,OAAOJ,SAOnD,GAAIwO,aAActP,QAAQ,iBACtBiN,KAAO,YAYPsL,UAAYjJ,YAAYpC,QAAQ,QAASqL,WAAUtU,KAAM6B,KAAMsI,MAAOoK,MAAOC,WAAYhI,SAAUlK,UACrG+I,YAAYpM,MAAMzB,MAAOwL,KAAMhJ,KAAMsC,WACrC9E,KAAK2M,MAAQA,MACb3M,KAAKqE,KAAOA,KACZrE,KAAK8O,MAAQiI,MACb/W,KAAKiX,SAAWD,WAChBhX,KAAKgP,SAAWA,UAGlBvP,QAAOJ,QAAUyX,YAEdzI,gBAAgB,KAAK6I,IAAI,SAAS3Y,QAAQkB,OAAOJ,SAMpD,YAEA,IAAI6M,WAAY3N,QAAQ,eACpBiN,KAAO,cAQP2L,YAAcjL,UAAUT,QAAQ,QAAS0L,aAAYC,MAAOtS,UAC9DoH,UAAUzK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKoX,MAAQA,OAGf3X,QAAOJ,QAAU8X,cAEd/K,cAAc,KAAKiL,IAAI,SAAS9Y,QAAQkB,OAAOJ;AAclD,GAAI0D,UAAW,SAAS+O,KAAMwF,OAAQnS,QACpCnF,KAAK8R,KAAOA,KACZ9R,KAAKsX,OAASA,OACdtX,KAAKmF,OAASA,OAGhB1F,QAAOJ,QAAU0D,cAEXwU,IAAI,SAAShZ,QAAQkB,OAAOJ,SAMlC,YAEA,IAAI6M,WAAY3N,QAAQ,eACpBiN,KAAO,OASPgM,KAAOtL,UAAUT,QAAQ,QAAS+L,MAAKnT,KAAMI,KAAMK,UACrDoH,UAAUzK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKqE,KAAOA,KACZrE,KAAKyE,KAAOA,MAGdhF,QAAOJ,QAAUmY,OAEdpL,cAAc,KAAKqL,IAAI,SAASlZ,QAAQkB,OAAOJ,SAMlD,YAEA,IAAI6M,WAAY3N,QAAQ,eACpBiN,KAAO,MASPkM,IAAMxL,UAAUT,QAAQ,QAASiM,KAAIrT,KAAMI,KAAMK,UACnDoH,UAAUzK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKqE,KAAOA,KACZrE,KAAKyE,KAAOA,MAGdhF,QAAOJ,QAAUqY,MAEdtL,cAAc,KAAKuL,IAAI,SAASpZ,QAAQkB,OAAOJ,SAOlD,GAAIwR,KAAMtS,QAAQ,SACdiN,KAAO,QAOPoM,MAAQ/G,IAAIpF,QAAQ,QAASmM,OAAMxW,KAAM0D,UAC3C+L,IAAIpP,MAAMzB,MAAOwL,KAAMpK,KAAM0D,YAG/BrF,QAAOJ,QAAUuY,QAEd7G,QAAQ,KAAK8G,IAAI,SAAStZ,QAAQkB,OAAOJ,SAO5C,GAAIiN,OAAQ/N,QAAQ,WAChBiN,KAAO,UAQPsM,QAAUxL,MAAMb,QAAQ,QAASqM,SAAQvL,SAAUwL,OAAQjT,UAC7DwH,MAAM7K,MAAMzB,MAAOwL,KAAMe,SAAUzH;AACnC9E,KAAK+X,OAASA,QAGhBtY,QAAOJ,QAAUyY,UAEdzH,UAAU,IAAI2H,IAAI,SAASzZ,QAAQkB,OAAOJ,SAO7C,GAAIwO,aAActP,QAAQ,iBACtBiN,KAAO,WAWPyM,SAAWpK,YAAYpC,QAAQ,QAASwM,UAASzV,KAAMmK,MAAOsB,MAAOnJ,UACvE+I,YAAYpM,MAAMzB,MAAOwL,KAAMhJ,KAAMsC,WACrC9E,KAAK2M,MAAQA,MACb3M,KAAKoO,WAAWH,QAGlBxO,QAAOJ,QAAU4Y,WAEd5J,gBAAgB,KAAK6J,IAAI,SAAS3Z,QAAQkB,OAAOJ,SAMpD,YACA,IAAIiW,QAAS/W,QAAQ,YACjBiN,KAAO,iBAOP2M,eAAiB7C,OAAO7J,QAAQ,QAAS0M,gBAAe1T,KAAMU,OAAQL,UACxEwQ,OAAO7T,MAAMzB,MAAOwL,KAAM/G,KAAMU,OAAQL,YAG1CrF,QAAOJ,QAAU8Y,iBAEdxB,WAAW,KAAKyB,IAAI,SAAS7Z,QAAQkB,OAAOJ,SAM/C,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,QAUP6M,MAAQvM,UAAUL,QAAQ,QAAS4M,OAAM7T,KAAM8T,SAAU5T,UAAWI,UACtEgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKwE,KAAOA,KACZxE,KAAKsY,SAAWA,SAChBtY,KAAK0E,UAAYA,WAGnBjF,QAAOJ,QAAUgZ,QAEdrM,cAAc,KAAKuM,IAAI,SAASha,QAAQkB,OAAOJ,SAMlD,YACA,IAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,SAQPgN,OAAS1L,KAAKrB,QAAQ,QAAS+M,QAAOC,KAAM3T;AAC9CgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAKyY,KAAOA,MAGdhZ,QAAOJ,QAAUmZ,SAEdvL,SAAS,KAAKyL,IAAI,SAASna,QAAQkB,OAAOJ,SAM7C,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,SAQPmN,OAAS7M,UAAUL,QAAQ,QAASkN,QAAOF,KAAM3T,UACnDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKyY,KAAOA,MAGdhZ,QAAOJ,QAAUsZ,SAEd3M,cAAc,KAAK4M,IAAI,SAASra,QAAQkB,OAAOJ,SAOlD,GAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,YAOPM,UAAYgB,KAAKrB,QAAQ,QAASK,WAAU5H,KAAMY,UACpDgI,KAAKrL,MAAMzB,MAAOkE,MAAQsH,KAAM1G,YAGlCrF,QAAOJ,QAAUyM,YAEdmB,SAAS,KAAK4L,IAAI,SAASta,QAAQkB,OAAOJ,SAM7C,YACA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,SAQPsN,OAAShN,UAAUL,QAAQ,QAASqN,QAAOnN,MAAO7G,UACpDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAK2L,MAAQA,OAGflM,QAAOJ,QAAUyZ,SAEd9M,cAAc,KAAK+M,IAAI,SAASxa,QAAQkB,OAAOJ,SAMlD,YACA,IAAIiW,QAAS/W,QAAQ,YACjBiN,KAAO,eAOPwN,aAAe1D,OAAO7J,QAAQ,QAASuN,cAAavU,KAAMU,OAAQL,UACpEwQ,OAAO7T,MAAMzB,MAAOwL,KAAM/G,KAAMU,OAAQL;EAG1CrF,QAAOJ,QAAU2Z,eAEdrC,WAAW,KAAKsC,IAAI,SAAS1a,QAAQkB,OAAOJ,SAO/C,GAAIoN,SAAUlO,QAAQ,aAClBiN,KAAO,SASP0N,OAASzM,QAAQhB,QAAQ,QAASyN,QAAOC,cAAexM,MAAO7H,UACjE2H,QAAQhL,MAAMzB,MAAOwL,KAAMmB,MAAO7H,WAClC9E,KAAKmZ,cAAgBA,eAGvB1Z,QAAOJ,QAAU6Z,SAEdtM,YAAY,KAAKwM,IAAI,SAAS7a,QAAQkB,OAAOJ,SAMhD,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,SAUP6N,OAASvN,UAAUL,QAAQ,QAAS4N,QAAO7U,KAAM8I,KAAM5B,UAAW5G,UACpEgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKwE,KAAOA,KACZxE,KAAKsN,KAAOA,KACZtN,KAAK0L,UAAYA,WAGnBjM,QAAOJ,QAAUga,SAEdrN,cAAc,KAAKsN,IAAI,SAAS/a,QAAQkB,OAAOJ,SAOlD,GAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,MAQPqF,IAAM/E,UAAUL,QAAQ,QAASoF,KAAI3M,KAAM9C,KAAM0D,UACnDgH,UAAUrK,MAAMzB,MAAOkE,MAAQsH,KAAM1G,WACrC9E,KAAKsB,UAAYF,MAGnB3B,QAAOJ,QAAUwR,MAEd7E,cAAc,KAAKuN,IAAI,SAAShb,QAAQkB,OAAOJ,SAMlD,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,QAQPgO,MAAQ1N,UAAUL,QAAQ,QAAS+N,OAAM/U,KAAMK;AACjDgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKyE,KAAOA,MAGdhF,QAAOJ,QAAUma,QAEdxN,cAAc,KAAKyN,IAAI,SAASlb,QAAQkB,OAAOJ,SAOlD,GAAIwO,aAActP,QAAQ,iBACtBiN,KAAO,QAWPkO,MAAQ7L,YAAYpC,QAAQ,QAASiO,OAAMlX,KAAMuL,IAAKC,KAAMV,KAAMxI,UACpE+I,YAAYpM,MAAMzB,MAAOwL,KAAMhJ,KAAMsC,WACrC9E,KAAKyL,QAAUsC,IACf/N,KAAKmO,WAAaH,KAClBhO,KAAKsN,KAAOA,MAGd7N,QAAOJ,QAAUqa,QAEdrL,gBAAgB,KAAKsL,IAAI,SAASpb,QAAQkB,OAAOJ,SAOpD,GAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,aAEPiE,UAAgB,SAChBC,aAAgB,YAChBC,WAAgB,UAWhBiK,WAAa9M,KAAKrB,QAAQ,QAASmO,YAAWC,MAAOC,OAAQC,GAAI9L,MAAOnJ,UAC1EgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAK6Z,MAAQA,MACb7Z,KAAK8Z,OAASA,OACd9Z,KAAK+Z,GAAKA,GACN9L,MACe,IAAbA,MAAM,GACRjO,KAAK8P,WAAaL,UACI,IAAbxB,MAAM,GACfjO,KAAK8P,WAAaJ,aAElB1P,KAAK8P,WAAaH,WAGpB3P,KAAK8P,WAAa,MAItBrQ,QAAOJ,QAAUua,aAEd3M,SAAS,KAAK+M,IAAI,SAASzb,QAAQkB,OAAOJ,SAO7C,GAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,kBAUPyO,gBAAkBnN,KAAKrB,QAAQ,QAASwO,iBAAgBJ,MAAOC,OAAQI,QAASpV;AAClFgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAK6Z,MAAQA,MACb7Z,KAAK8Z,OAASA,OACd9Z,KAAKka,QAAUA,SAGjBza,QAAOJ,QAAU4a,kBAEdhN,SAAS,KAAKkN,IAAI,SAAS5b,QAAQkB,OAAOJ,SAO7C,GAAIyN,MAAOvO,QAAQ,UACfiN,KAAO,WASP4O,SAAWtN,KAAKrB,QAAQ,QAAS2O,UAASC,OAAQC,YAAaxV,UACjEgI,KAAKrL,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAKqa,OAASA,OACdra,KAAKsa,YAAcA,aAGrB7a,QAAOJ,QAAU+a,WAEdnN,SAAS,KAAKsN,IAAI,SAAShc,QAAQkB,OAAOJ,SAM7C,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,MAUPgP,IAAM1O,UAAUL,QAAQ,QAAS+O,KAAIlN,KAAMmN,QAASC,OAAQ5V,UAC9DgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKsN,KAAOA,KACZtN,KAAKya,QAAUA,QACfza,KAAK0a,OAASA,QAGhBjb,QAAOJ,QAAUmb,MAEdxO,cAAc,KAAK2O,IAAI,SAASpc,QAAQkB,OAAOJ,SAMlD,YAEA,IAAI6M,WAAY3N,QAAQ,eACpBiN,KAAO,QASPoP,MAAQ1O,UAAUT,QAAQ,QAASmP,OAAMvW,KAAMI,KAAMK,UACvDoH,UAAUzK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKqE,KAAOA,KACZrE,KAAKyE,KAAOA,MAGdhF,QAAOJ,QAAUub,QAEdxO,cAAc,KAAKyO,IAAI,SAAStc,QAAQkB,OAAOJ,SAOlD,GAAIwR,KAAMtS,QAAQ,SACdiN,KAAO,QAOPsP,MAAQjK,IAAIpF,QAAQ,QAASqP,OAAM1Z,KAAM0D;AAC3C+L,IAAIpP,MAAMzB,MAAOwL,KAAMpK,KAAM0D,YAG/BrF,QAAOJ,QAAUyb,QAEd/J,QAAQ,KAAKgK,IAAI,SAASxc,QAAQkB,OAAOJ,SAM5C,YACA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,WAYPwP,SAAWlP,UAAUL,QAAQ,QAASuP,UAASxY,KAAM6B,KAAMsH,MAAO7G,UACpEgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKwC,KAAOA,KACZxC,KAAKqE,KAAOA,KACZrE,KAAK2L,MAAQA,OAGflM,QAAOJ,QAAU2b,WAEdhP,cAAc,KAAKiP,IAAI,SAAS1c,QAAQkB,OAAOJ,SAMlD,YACA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,UAYP0P,QAAUpP,UAAUL,QAAQ,QAASyP,SAAQ1Y,KAAM2Y,MAAO9W,KAAMS,UAClEgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKwC,KAAOA,KACZxC,KAAKmb,MAAQA,MACbnb,KAAKqE,KAAOA,MAQd6W,SAAQE,WAAa,QAKrBF,QAAQG,cAAgB,WAGxB5b,OAAOJ,QAAU6b,UAEdlP,cAAc,KAAKsP,IAAI,SAAS/c,QAAQkB,OAAOJ,SAMlD,YACA,IAAIkM,MAAOhN,QAAQ,gBACfiN,KAAO,WAqBP+P,SAAWhQ,KAAKE,QAAQ,QAAS8P,UAAS/Y,KAAMsM,MAAO0M,MAAO1W,UAChEyG,KAAK9J,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAKwC,KAAOA,KACZxC,KAAK8O,MAAQA,QAAS,EACtB9O,KAAKwb,MAAQA,QAAS,GAGxB/b,QAAOJ,QAAUkc;AAEd3P,eAAe,KAAK6P,IAAI,SAASld,QAAQkB,OAAOJ,SAMnD,YACA,IAAIkM,MAAOhN,QAAQ,gBACfiN,KAAO,WASPkQ,SAAWnQ,KAAKE,QAAQ,QAASiQ,UAASjX,KAAMK,UAClDyG,KAAK9J,MAAMzB,MAAOwL,KAAM1G,WACxB9E,KAAKyE,KAAOA,MAGdhF,QAAOJ,QAAUqc,WAEd9P,eAAe,KAAK+P,IAAI,SAASpd,QAAQkB,OAAOJ,SAMnD,YAEA,IAAIyM,WAAYvN,QAAQ,eACpBiN,KAAO,QAUPoQ,MAAQ9P,UAAUL,QAAQ,QAASmQ,OAAMpX,KAAM8I,KAAM5B,UAAW5G,UAClEgH,UAAUrK,MAAMzB,MAAOwL,KAAM1G,WAC7B9E,KAAKwE,KAAOA,KACZxE,KAAKsN,KAAOA,KACZtN,KAAK0L,UAAYA,WAGnBjM,QAAOJ,QAAUuc,QAEd5P,cAAc,KAAK6P,IAAI,SAAStd,QAAQkB,OAAOJ,SAMlD,YAEA,IAAIkT,YAAahU,QAAQ,gBACrBiN,KAAO,QAUPsQ,MAAQvJ,WAAW9G,QAAQ,QAASqQ,OAAMnP,MAAO+E,IAAK5M,UACxDyN,WAAW9Q,MAAMzB,MAAOwL,KAAM1G,WAC9B9E,KAAK2M,MAAQA,MACb3M,KAAK0R,IAAMA,KAGbjS,QAAOJ,QAAUyc,QAEdlQ,eAAe,KAAKmQ,IAAI,SAASxd,QAAQkB,OAAOJ,SAMnD,YAEA,IAAIkT,YAAahU,QAAQ,gBACrBiN,KAAO,YASPwQ,UAAYzJ,WAAW9G,QAAQ,QAASuQ,WAAUrP,MAAO7H,UAC3DyN,WAAW9Q,MAAMzB,MAAOwL,KAAM1G;AAC9B9E,KAAK2M,MAAQA,OAGflN,QAAOJ,QAAU2c,YAEdpQ,eAAe,KAAKqQ,IAAI,SAAS1d,QAAQkB,OAAOJ,SAMnD,YAeA,IAAIgE,OAAQ,SAAS6Y,QACnBlc,KAAKkc,OAASA,OACdlc,KAAKmc,IAAMnc,KAAKkc,OAAOE,OAAOC,MAC9Brc,KAAKsc,IAAM,EACXtc,KAAKuc,OAAQ,EACbvc,KAAKwc,YAAa,EAClBxc,KAAKyc,gBAAiB,EACtBzc,KAAK0c,WAAY,EACjB1c,KAAK2c,UAAW,EAChB3c,KAAK4c,YAAa,EAClB5c,KAAK6c,UAAY,EACjB7c,KAAK8c,UACHC,UAAa/c,KAAKmc,IAAIa,UACtBC,UAAajd,KAAKmc,IAAIe,UACtBC,aAAgBnd,KAAKmc,IAAIiB,SACzBC,WAAcrd,KAAKmc,IAAImB,WACvBC,SAAYvd,KAAKmc,IAAIqB,OACrBC,SAAYzd,KAAKmc,IAAIuB,OACrBC,QAAW3d,KAAKmc,IAAIyB,MACpBC,cAAiB7d,KAAKmc,IAAI2B,OAC1BC,KAAQ/d,KAAKmc,IAAI6B,OACjBC,IAAOje,KAAKmc,IAAI6B,OAChBE,SAAYle,KAAKmc,IAAIgC,WACrBC,MAASpe,KAAKmc,IAAIkC,QAClBC,OAAUte,KAAKmc,IAAIoC,SACnBC,IAAOxe,KAAKmc,IAAIsC,MAChBC,MAAS1e,KAAKmc,IAAIwC,QAClBC,QAAW5e,KAAKmc,IAAI0C,UACpBC,MAAS9e,KAAKmc,IAAI4C,QAClBC,GAAMhf,KAAKmc,IAAI8C,KACfC,OAAUlf,KAAKmc,IAAIgD,SACnBC,MAASpf,KAAKmc,IAAIkD,QAClBC,KAAQtf,KAAKmc,IAAIoD,OACjBC,MAASxf,KAAKmc,IAAIsD,QAClBC,SAAY1f,KAAKmc,IAAIwD,WACrBC,GAAM5f,KAAKmc,IAAI0D,KACfC,IAAO9f,KAAKmc,IAAI4D,MAChBC,OAAUhgB,KAAKmc,IAAI8D,SACnBC,QAAWlgB,KAAKmc,IAAIgE,UACpBC,WAAcpgB,KAAKmc,IAAIkE;AACvBC,QAAWtgB,KAAKmc,IAAIoE,UACpBC,WAAcxgB,KAAKmc,IAAIsE,aACvBC,WAAc1gB,KAAKmc,IAAIwE,aACvB5G,GAAM/Z,KAAKmc,IAAIyE,KACfC,OAAU7gB,KAAKmc,IAAI2E,SACnBC,UAAa/gB,KAAKmc,IAAI6E,YACtBC,KAAQjhB,KAAKmc,IAAI+E,OACjBC,QAAWnhB,KAAKmc,IAAIiF,UACpBC,MAASrhB,KAAKmc,IAAImF,QAClBC,SAAYvhB,KAAKmc,IAAIqF,WACrBC,KAAQzhB,KAAKmc,IAAIuF,OACjBC,KAAQ3hB,KAAKmc,IAAIyF,OACjBC,MAAS7hB,KAAKmc,IAAI2F,QAClBC,MAAS/hB,KAAKmc,IAAI6F,QAClBC,UAAajiB,KAAKmc,IAAI+F,YACtBrI,MAAS7Z,KAAKmc,IAAIgG,QAClB1W,QAAWzL,KAAKmc,IAAIiG,UACpBjU,WAAcnO,KAAKmc,IAAIkG,aACvBC,IAAOtiB,KAAKmc,IAAIoG,MAChBC,MAASxiB,KAAKmc,IAAIsG,QAClBC,IAAO1iB,KAAKmc,IAAIwG,MAChBC,KAAQ5iB,KAAKmc,IAAI0G,OACjBC,QAAW9iB,KAAKmc,IAAI4G,UACpBC,aAAgBhjB,KAAKmc,IAAI8G,eACzB1kB,QAAWyB,KAAKmc,IAAI+G,UACpBC,aAAgBnjB,KAAKmc,IAAIiH,eACzBC,UAAarjB,KAAKmc,IAAImH,YACtBC,IAAOvjB,KAAKmc,IAAIqH,MAChBC,UAAazjB,KAAKmc,IAAIuH,YACtBC,OAAU3jB,KAAKmc,IAAIyH,SACnBC,MAAS7jB,KAAKmc,IAAI2H,QAClBC,MAAS/jB,KAAKmc,IAAI6H,QAClBC,gBAAmBjkB,KAAKmc,IAAI+H,gBAC5BC,OAAUnkB,KAAKmc,IAAIiI,SACnBC,SAAYrkB,KAAKmc,IAAImI,WACrBC,MAASvkB,KAAKmc,IAAIqI,QAClBC,QAAWzkB,KAAKmc,IAAIuI,UACpBC,UAAa3kB,KAAKmc,IAAIyI,YACtBC,OAAU7kB,KAAKmc,IAAI2I;AACnBC,MAAS/kB,KAAKmc,IAAI6I,QAClBphB,KAAQ5D,KAAKmc,IAAI8I,OACjBjkB,MAAShB,KAAKmc,IAAI+I,QAClBC,SAAYnlB,KAAKmc,IAAIiJ,WACrBC,GAAMrlB,KAAKmc,IAAImJ,aACfC,IAAOvlB,KAAKmc,IAAIqJ,cAChBC,IAAOzlB,KAAKmc,IAAIuJ,eAElB1lB,KAAK2lB,cACHC,IAAO5lB,KAAKmc,IAAI0J,WAChBC,QAAW9lB,KAAKmc,IAAI0J,WACpBE,KAAQ/lB,KAAKmc,IAAI6J,cACjBC,OAAUjmB,KAAKmc,IAAI6J,cACnBE,MAASlmB,KAAKmc,IAAI6J,cAClBG,OAAUnmB,KAAKmc,IAAIiK,cACnBC,OAAUrmB,KAAKmc,IAAIiK,cACnBplB,MAAShB,KAAKmc,IAAImK,aAClBC,OAAUvmB,KAAKmc,IAAIqK,cACnBC,KAAQzmB,KAAKmc,IAAIuK,YACjBC,QAAW3mB,KAAKmc,IAAIuK,YACpB3B,MAAS/kB,KAAKmc,IAAIyK,cAOtBvjB,OAAM7B,UAAUqlB,SAAW,SAASC,OAyBlC,MAxBA9mB,MAAKiF,OAAS6hB,MACd9mB,KAAK+mB,KAAOD,MAAMvnB,OAClBS,KAAKgnB,SAAW,EAChBhnB,KAAKmF,OAAS,EACdnF,KAAK6c,UAAY,EACjB7c,KAAKinB,OAAS,GACdjnB,KAAKsD,QACHG,aAAc,EACdF,WAAY,EACZC,aAAc,EACd4B,YAAa,EACbC,UAAW,EACXC,YAAa,EACb4hB,UAAW,EACXC,YAAa,GAEfnnB,KAAKoc,UACLpc,KAAKonB,kBACLpnB,KAAKqnB,KAAOrnB,KAAKmF,QAAUnF,KAAK+mB,MAC3B/mB,KAAKwc,YAAcxc,KAAK0c,UAC3B1c,KAAKsnB,MAAM,mBAEXtnB,KAAKsnB,MAAM,WAENtnB,MAOTqD,MAAM7B,UAAUslB,MAAQ,SAASC,MAC/B,GAAIQ,IAAKvnB,KAAKiF,OAAOjF,KAAKmF;AAC1B,MAAKoiB,KACLvnB,KAAKinB,QAAUM,GACfvnB,KAAKmF,SACO,OAAPoiB,IAA4C,OAA7BvnB,KAAKiF,OAAOjF,KAAKmF,UACnCnF,KAAKinB,QAAU,KACfjnB,KAAKmF,UAEI,OAAPoiB,IAAsB,OAAPA,IACjBvnB,KAAKsD,OAAO4jB,YAAclnB,KAAKgnB,SAC/BhnB,KAAK6c,UAAY7c,KAAKsD,OAAO6jB,YAC7BnnB,KAAKsD,OAAO6jB,YAAc,GAE1BnnB,KAAKsD,OAAO6jB,cAEPI,IAdS,IAoBlBlkB,MAAM7B,UAAUgmB,MAAQ,SAAST,MAC/B,GAAa,IAATA,KAEF/mB,KAAKmF,SAC4B,OAA7BnF,KAAKiF,OAAOjF,KAAKmF,SAAqD,OAAjCnF,KAAKiF,OAAOjF,KAAKmF,OAAS,KACjEnF,KAAKmF,SACL4hB,QAE+B,OAA7B/mB,KAAKiF,OAAOjF,KAAKmF,SAAiD,OAA7BnF,KAAKiF,OAAOjF,KAAKmF,SACxDnF,KAAKsD,OAAO4jB,YACZlnB,KAAKgnB,WACLhnB,KAAKsD,OAAO6jB,YAAcnnB,KAAK6c,WAE/B7c,KAAKsD,OAAO6jB,cAEdnnB,KAAKinB,OAASjnB,KAAKinB,OAAO/hB,UAAU,EAAGlF,KAAKinB,OAAO1nB,OAASwnB,UACvD,IAAIA,KAAO,EAEhB,GADA/mB,KAAKmF,QAAU4hB,KACXA,KAAO/mB,KAAKinB,OAAO1nB,OAAQ,CAC7BS,KAAKinB,OAASjnB,KAAKinB,OAAO/hB,UAAU,EAAGlF,KAAKinB,OAAO1nB,OAASwnB,MAE5D/mB,KAAKsD,OAAO4jB,UAAYlnB,KAAKsD,OAAOC,WACpCvD,KAAKsD,OAAO6jB,YAAcnnB,KAAK6c,UAAY7c,KAAKsD,OAAOE,YACvD,KAAI,GAAIxE,GAAI,EAAGA,EAAIgB,KAAKinB,OAAO1nB,OAAQP,IAAK,CAC1C,GAAIyoB,GAAIznB,KAAKinB,OAAOjoB,EACV,QAANyoB,GACFA,EAAIznB,KAAKinB,SAASjoB,GAClBgB,KAAK6c,UAAY7c,KAAKsD,OAAO6jB,YAC7BnnB,KAAKsD,OAAO4jB;AACZlnB,KAAKsD,OAAO6jB,YAAc,EAChB,OAANM,IACQ,OAANA,EACFznB,KAAKsD,OAAO4jB,YAEZlnB,KAAKsD,OAAO6jB,gBAGD,OAANM,GACTznB,KAAK6c,UAAY7c,KAAKsD,OAAO6jB,YAC7BnnB,KAAKsD,OAAO4jB,YACZlnB,KAAKsD,OAAO6jB,YAAc,GAE1BnnB,KAAKsD,OAAO6jB,cAGhBnnB,KAAKgnB,SAAWhnB,KAAKsD,OAAO4jB,cAG5BlnB,MAAKinB,OAAS,GACdjnB,KAAKsD,OAAO4jB,UAAYlnB,KAAKgnB,SAAWhnB,KAAKsD,OAAOC,WACpDvD,KAAKsD,OAAO6jB,YAAcnnB,KAAKsD,OAAOE,YAI1C,OAAOxD,OAITqD,MAAM7B,UAAUkmB,SAAW,SAASC,MAClC,MAAOA,QAAS3nB,KAAK4nB,MAAMD,KAAKpoB,SAIlC8D,MAAM7B,UAAUqmB,iBAAmB,SAASF,MAC1C,MAAOA,QAAS3nB,KAAK4nB,MAAMD,KAAKpoB,QAAQsG,eAI1CxC,MAAM7B,UAAUomB,MAAQ,SAASb,MAC/B,GAAIY,MAAO3nB,KAAKiF,OAAOC,UAAUlF,KAAKmF,OAAQnF,KAAKmF,OAAS4hB,KAI5D,OAH8B,OAA1BY,KAAKA,KAAKpoB,OAAS,IAAuD,OAAxCS,KAAKiF,OAAOjF,KAAKmF,OAAS4hB,KAAO,KACrEY,MAAQ,MAEHA,MAITtkB,MAAM7B,UAAUsmB,QAAU,SAASf,MACjC,IAAI,GAAI/nB,GAAI,EAAGA,EAAI+nB,KAAM/nB,IAAK,CAC5B,GAAIuoB,IAAKvnB,KAAKiF,OAAOjF,KAAKmF,OAC1B,KAAKoiB,GAAI,KACTvnB,MAAKinB,QAAUM,GACfvnB,KAAKmF,SACO,OAAPoiB,IAA4C,OAA7BvnB,KAAKiF,OAAOjF,KAAKmF,UACnCnF,KAAKinB,QAAU,KACfjnB,KAAKmF,SACLnG,KAES,OAAPuoB,IAAsB,OAAPA,IACjBvnB,KAAKsD,OAAO4jB,YAAclnB,KAAKgnB;AAC/BhnB,KAAK6c,UAAY7c,KAAKsD,OAAO6jB,YAC7BnnB,KAAKsD,OAAO6jB,YAAc,GAE1BnnB,KAAKsD,OAAO6jB,cAGhB,MAAOnnB,OAMTqD,MAAM7B,UAAUumB,SAAW,WACzB,OACEd,OAAQjnB,KAAKinB,OACb9hB,OAAQnF,KAAKmF,OACb6hB,SAAUhnB,KAAKgnB,SACfnK,UAAW7c,KAAK6c,UAChBvZ,QACEG,aAAczD,KAAKsD,OAAOG,aAC1BF,WAAYvD,KAAKsD,OAAOC,WACxBC,aAAcxD,KAAKsD,OAAOE,aAC1B0jB,UAAWlnB,KAAKsD,OAAO4jB,UACvBC,YAAannB,KAAKsD,OAAO6jB,eAQ/B9jB,MAAM7B,UAAUwmB,SAAW,SAASC,OAMlC,MALAjoB,MAAKinB,OAASgB,MAAMhB,OACpBjnB,KAAKmF,OAAS8iB,MAAM9iB,OACpBnF,KAAKgnB,SAAWiB,MAAMjB,SACtBhnB,KAAK6c,UAAYoL,MAAMpL,UACvB7c,KAAKsD,OAAS2kB,MAAM3kB,OACbtD,MAITqD,MAAM7B,UAAU0mB,YAAc,SAASvb,MAAOib,OAE5C,MADA5nB,MAAKoc,OAAO7a,MAAMoL,MAAOib,QAClB5nB,MAITqD,MAAM7B,UAAU2mB,IAAM,WACpBnoB,KAAKsD,OAAO8B,YAAcpF,KAAKmF,OAC/BnF,KAAKsD,OAAO+B,UAAYrF,KAAKsD,OAAO4jB,UACpClnB,KAAKsD,OAAOgC,YAActF,KAAKsD,OAAO6jB,WACtC,IAAItV,OAAQ7R,KAAKooB,QAAUpoB,KAAKmoB,KAChC,KAAKnoB,KAAKwc,WAAY,CACpB,KACE3K,QAAU7R,KAAKmc,IAAIkM,eAEhBroB,KAAKyc,iBACJ5K,QAAU7R,KAAKmc,IAAImM,WAChBzW,QAAU7R,KAAKmc,IAAIoM,gBAKxB1W,QAAU7R,KAAKmc,IAAIqM,YAGrB3W,MAAQ7R,KAAKooB,QAAUpoB,KAAKmoB;AAE9B,IAAKnoB,KAAK0c,WAAa7K,OAAS7R,KAAKmc,IAAIsM,qBAEvC,MAAOzoB,MAAKmc,IAAIyF,OAWpB,MARK5hB,MAAKsD,OAAO8B,cACfpF,KAAKsD,OAAO8B,YAAcpF,KAAKsD,OAAOG,aACtCzD,KAAKsD,OAAO+B,UAAYrF,KAAKsD,OAAOC,WACpCvD,KAAKsD,OAAOgC,YAActF,KAAKsD,OAAOE,cAKjCqO,OAITxO,MAAM7B,UAAU8lB,MAAQ,SAASoB,WAI/B,GAHA1oB,KAAKonB,eAAe7lB,KAAKmnB,WACzB1oB,KAAK2oB,aAAeD,UACpB1oB,KAAK4oB,QAAU5oB,KAAK,QAAU0oB,WACF,kBAAjB1oB,MAAK4oB,QACd,KAAM,IAAI1pB,OAAM,8BAA8BwpB,UAAU,IAE1D,OAAO1oB,OAITqD,MAAM7B,UAAUqnB,SAAW,WACzB,GAAInqB,GAAIsB,KAAKonB,eAAe7nB,OAAS,EACjCmpB,UAAahqB,EAAI,EAAKsB,KAAKonB,eAAe0B,MAAQ9oB,KAAKonB,eAAe,EAG1E,IAFApnB,KAAK2oB,aAAe3oB,KAAKonB,eAAepnB,KAAKonB,eAAe7nB,OAAS,GACrES,KAAK4oB,QAAU5oB,KAAK,QAAUA,KAAK2oB,cACP,kBAAjB3oB,MAAK4oB,QACd,KAAM,IAAI1pB,OAAM,8BAA8Bc,KAAK2oB,aAAa,IAElE,OAAOD,YAITrlB,MAAM7B,UAAU4mB,KAAO,WACrB,GAAIvW,MAQJ,IAPK7R,KAAKiF,SACRjF,KAAKqnB,MAAO,GAEdrnB,KAAKsD,OAAOG,aAAezD,KAAKmF,OAChCnF,KAAKsD,OAAOC,WAAavD,KAAKsD,OAAO4jB;AACrClnB,KAAKsD,OAAOE,aAAexD,KAAKsD,OAAO6jB,YACvCnnB,KAAKinB,OAAS,GACVjnB,KAAKqnB,KAIP,MAHArnB,MAAKsD,OAAO8B,YAAcpF,KAAKsD,OAAOG,aACtCzD,KAAKsD,OAAO+B,UAAYrF,KAAKsD,OAAOC,WACpCvD,KAAKsD,OAAOgC,YAActF,KAAKsD,OAAOE,aAC/BxD,KAAKsc,GAgBd,IAdItc,KAAKoc,OAAO7c,OAAS,GACvBsS,MAAQ7R,KAAKoc,OAAO7W,QACI,gBAAbsM,OAAM,GACf7R,KAAKgoB,SAASnW,MAAM,IAEpB7R,KAAK8nB,QAAQjW,MAAM,IAErBA,MAAQA,MAAM,IAEdA,MAAQ7R,KAAK4oB,QAAQnnB,MAAMzB,SAEzBA,KAAKmF,QAAUnF,KAAK+mB,MAA+B,IAAvB/mB,KAAKoc,OAAO7c,SAC1CS,KAAKqnB,MAAO,GAEVrnB,KAAKuc,MAAO,CACd,GAAIwM,OAAQlX,KAEVkX,OADmB,gBAAVA,OACD/oB,KAAKkc,OAAOE,OAAO4M,OAAOD,OAE1B,IAAIA,MAAM,GAEpB,IAAIvqB,GAAI,GAAIU,OACV6pB,MACA,UAAY/oB,KAAKsD,OAAOC,WAAa,IAAMvD,KAAKsD,OAAOE,aACvD,WAAaxD,KAAKsD,OAAO4jB,UAAY,IAAMlnB,KAAKsD,OAAO6jB,YACvD,MAAMnnB,KAAKinB,OAAO,IAEpBgC,SAAQC,IAAI1qB,EAAE2qB,OAEhB,MAAOtX,SAMPtT,QAAQ,uBACRA,QAAQ,sBACRA,QAAQ,sBACRA,QAAQ,uBACRA,QAAQ,wBACRA,QAAQ,sBACRA,QAAQ,qBACRA,QAAQ,qBACRoF,QAAQ,SAAUoK;AAClB,IAAI,GAAIqb,KAAKrb,KACX1K,MAAM7B,UAAU4nB,GAAKrb,IAAIqb,KAI7B3pB,OAAOJ,QAAUgE,QAEdgmB,sBAAsB,GAAGC,qBAAqB,GAAGC,qBAAqB,GAAGC,sBAAsB,GAAGC,uBAAuB,GAAGC,qBAAqB,GAAGC,oBAAoB,GAAGC,mBAAmB,KAAKC,IAAI,SAAStrB,QAAQkB,OAAOJ,SAOlO,YAEAI,QAAOJ,SAKLipB,UAAW,WACT,KAAMtoB,KAAKmF,OAASnF,KAAK+mB,MAAM,CAC7B,GAAIQ,IAAKvnB,KAAK8mB,OACd,IAAW,OAAPS,IAAsB,OAAPA,GACjB,MAAOvnB,MAAKmc,IAAImM,SACX,IAAW,MAAPf,KAAevnB,KAAK8pB,YAA2C,MAA7B9pB,KAAKiF,OAAOjF,KAAKmF,QAE5D,MADAnF,MAAKwnB,MAAM,GACJxnB,KAAKmc,IAAImM,SACX,IAAW,MAAPf,IAAcvnB,KAAK8pB,YAA2C,MAA7B9pB,KAAKiF,OAAOjF,KAAKmF,QAE3D,MADAnF,MAAKwnB,MAAM,GACJxnB,KAAKmc,IAAImM,UAGpB,MAAOtoB,MAAKmc,IAAImM,WAKlBC,cAAe,WACb,GAAIhB,IAAKvnB,KAAK8mB,QACVjV,MAAQ7R,KAAKmc,IAAImM,SACrB,IAAW,MAAPf,GAAY,CAKd,GAJAA,GAAKvnB,KAAK8mB,QACN9mB,KAAK+pB,kBACPlY,MAAQ7R,KAAKmc,IAAIoM,eAER,MAAPhB,GACF,MAAO1V,MAEP7R,MAAKwnB,MAAM,GAGf,KAAMxnB,KAAKmF,OAASnF,KAAK+mB,MAEvB,GADAQ,GAAKvnB,KAAK8mB,QACC,MAAPS,IAA2C,MAA7BvnB,KAAKiF,OAAOjF,KAAKmF,QAAiB,CAClDnF,KAAK8mB,OACL,OAGJ,MAAOjV,cAILmY,IAAI,SAASzrB,QAAQkB,OAAOJ;AAMlCI,OAAOJ,SACL4qB,YAAa,WAUX,MAREjqB,MAAKonB,eAAe7nB,OAAS,GAC+B,YAAzDS,KAAKonB,eAAepnB,KAAKonB,eAAe7nB,OAAS,GAGpDS,KAAK6oB,WAEL7oB,KAAKsnB,MAAM,mBAENtnB,MAETkqB,aAAc,WACZ,KAAMlqB,KAAKmF,OAASnF,KAAK+mB,MAAM,CAC7B,GAAIQ,IAAKvnB,KAAK8mB,OACd,IAAU,KAANS,GAEF,GADAA,GAAKvnB,KAAK4nB,MAAM,GACN,KAANL,GAAW,CACb,GAAIvnB,KAAK0nB,SAAS,MAAO,CACvB1nB,KAAKwnB,MAAM,GAAGU,YAAYloB,KAAKmc,IAAIsM,qBAAsB,GAAGwB,aAC5D,OACK,GAAIjqB,KAAK6nB,iBAAiB,UAC/BN,GAAKvnB,KAAKiF,OAAOjF,KAAKmF,OAAS,GACpB,MAAPoiB,IAAqB,OAAPA,IAAsB,OAAPA,IAAsB,OAAPA,IAAa,CAC3DvnB,KAAKwnB,MAAM,GAAGU,YAAYloB,KAAKmc,IAAIqM,WAAY,GAAGyB,aAClD,OAGJ,GAAIjqB,KAAK4c,WAAY,CACnB5c,KAAKwnB,MAAM,GAAGU,YAAYloB,KAAKmc,IAAIqM,WAAY,GAAGyB,aAClD,YAEG,IAAGjqB,KAAK2c,UAAkB,KAAN4K,GAAW,CACpC,GAAIvnB,KAAK0nB,SAAS,MAAO,CACvB1nB,KAAK8pB,YAAa,EAClB9pB,KAAKwnB,MAAM,GAAGU,YAAYloB,KAAKmc,IAAIsM,qBAAsB,GAAGwB,aAC5D,OAEAjqB,KAAK8pB,YAAa,EAClB9pB,KAAKwnB,MAAM,GAAGU,YAAYloB,KAAKmc,IAAIqM,WAAY,GAAGyB,aAClD,QAKR,MAAIjqB,MAAKinB,OAAO1nB,OAAS,GAChBS,KAAKmc,IAAIgO,qBAOhBC,IAAI,SAAS7rB,QAAQkB,OAAOJ,UAClC,SAAW6B;AAOX,YAGA,IAAoB,OAAhBA,QAAQmpB,KACV,GACIC,oBAAqB,GACrBC,gBAAkB,0BAEtB,IACID,oBAAqB,GACrBC,gBAAkB,YAGxB9qB,QAAOJ,SACLmrB,YAAa,WACX,GAAIjD,IAAKvnB,KAAKinB,OAAO,GACjBwD,SAA8B,MAAnBzqB,KAAKinB,OAAO,EAC3B,IAAW,MAAPM,GAGF,GAFAA,GAAKvnB,KAAK8mB,QAEC,MAAPS,IAAqB,MAAPA,GAAY,CAE5B,GADAvnB,KAAK8mB,QACD9mB,KAAK0qB,SACP,MAAO1qB,MAAK2qB,cAEZ3qB,MAAKwnB,MAAM,OAER,IAAW,MAAPD,IAAqB,MAAPA,GAAY,CAEnC,GADAA,GAAKvnB,KAAK8mB,QACC,MAAPS,IAAqB,MAAPA,GAChB,MAAOvnB,MAAK4qB,cAEZ5qB,MAAKwnB,MAAM,OAEHxnB,MAAK6qB,UACf7qB,KAAKwnB,MAAM,EAIf,MAAMxnB,KAAKmF,OAASnF,KAAK+mB,MAEvB,GADAQ,GAAKvnB,KAAK8mB,SACL9mB,KAAK6qB,SAAU,CAClB,GAAW,MAAPtD,IAAekD,SAEZ,CAAA,GAAW,MAAPlD,IAAqB,MAAPA,GAAY,CAEnC,GADAA,GAAKvnB,KAAK8mB,QACC,MAAPS,IAAqB,MAAPA,GAAY,CAE5B,GADAA,GAAKvnB,KAAK8mB,QACN9mB,KAAK6qB,SAEP,MADA7qB,MAAK8qB,eACE9qB,KAAKmc,IAAI4O,SAEZxD,KAAIvnB,KAAKwnB,MAAM,EACnB,OAEG,GAAIxnB,KAAK6qB,SAEd,MADA7qB,MAAK8qB,eACE9qB,KAAKmc,IAAI4O,SAEZxD,KAAIvnB,KAAKwnB,MAAM,EACnB,OAGFxnB,KAAKwnB,MAAM,EACX,OArBAiD,UAAW,EAyBjB,MAAIA,UACKzqB,KAAKmc,IAAI4O,UACP/qB,KAAKinB,OAAO1nB,OAAS+qB,mBAAqB,EAC5CtqB,KAAKmc,IAAI6O,UAGdhrB,KAAKinB,OAAO1nB,OAAS+qB,oBACnBtqB,KAAKinB,OAAO1nB,QAAU+qB,oBACnBtqB,KAAKinB,OAASsD,gBAGZvqB,KAAKmc,IAAI6O,UAEXhrB,KAAKmc,IAAI4O;EAIpBJ,aAAc,WACZ,KAAM3qB,KAAKmF,OAASnF,KAAK+mB,MAEvB,GADA/mB,KAAK8mB,SACA9mB,KAAK0qB,SAAU,CAClB1qB,KAAKwnB,MAAM,EACX,OAGJ,MAAOxnB,MAAKmc,IAAI6O,WAGlBF,aAAc,WACZ,KAAM9qB,KAAKmF,OAASnF,KAAK+mB,MAEvB,GADA/mB,KAAK8mB,SACA9mB,KAAK6qB,SAAU,CAClB7qB,KAAKwnB,MAAM,EACX,OAGJ,MAAOxnB,MAAKmc,IAAI6O,WAGlBJ,aAAc,WAEZ,IADA,GAAIrD,IACEvnB,KAAKmF,OAASnF,KAAK+mB,MAEvB,GADAQ,GAAKvnB,KAAK8mB,QACC,MAAPS,IAAqB,MAAPA,GAAY,CACxBA,IAAIvnB,KAAKwnB,MAAM,EACnB,OAGJ,MAAOxnB,MAAKmc,IAAI6O,cAIjB1rB,KAAKU,KAAKzB,QAAQ,eAClB0sB,SAAW,IAAIC,IAAI,SAAS3sB,QAAQkB,OAAOJ,SAM9CI,OAAOJ,SACL8rB,6BAA8B,WAC5B,GAAI5D,IAAKvnB,KAAK8mB,OACd,IAAW,MAAPS,GAAY,CAEd,GADAA,GAAKvnB,KAAK8mB,QACC,MAAPS,GAEF,MAAOvnB,MAAKmc,IAAIiP,iBAEd7D,KAAIvnB,KAAKwnB,MAAM,OACd,IAAIxnB,KAAKqrB,iBAId,MAFArrB,MAAKsrB,gBACLtrB,KAAK6oB,WACE7oB,KAAKmc,IAAIoP,QAKlB,OAFAvrB,MAAK6oB,WACDtB,IAAIvnB,KAAKwnB,MAAM,IACZ,GAETgE,4BAA6B,WAC3B,GAAIjE,IAAKvnB,KAAK8mB,OACd,OAAI9mB,MAAKqrB,kBACPrrB,KAAKsrB,gBACL/D,GAAKvnB,KAAK8mB,QACV9mB,KAAK6oB,WACM,MAAPtB,IAAqB,MAAPA,IAChBvnB,KAAKsnB,MAAM,mBACXtnB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAIsP,mBAEhBzrB,KAAKwnB,MAAMxnB,KAAKinB,OAAO1nB;CAChB,KAGLgoB,IAAIvnB,KAAKwnB,MAAM,GACnBxnB,KAAK6oB,WACL7oB,KAAKsnB,MAAM,oBAEJ,IAGXoE,mBAAoB,WAClB,GAAInE,IAAKvnB,KAAK8mB,OACd,IAAI9mB,KAAK6qB,SAEP,MADA7qB,MAAKwqB,cACExqB,KAAKmc,IAAIwP,YACX,IAAW,MAAPpE,GAET,MADAvnB,MAAK6oB,WACE,GACF,IAAW,MAAPtB,GAAY,CAErB,GADAvnB,KAAK8mB,QACD9mB,KAAKqrB,iBAEP,MADArrB,MAAKsrB,gBACEtrB,KAAKmc,IAAIyP,UAEhB,MAAM,IAAI1sB,OAAM,uBAEb,GAAIc,KAAKqrB,iBAEd,MADArrB,MAAKsrB,gBACEtrB,KAAKmc,IAAIoP,QACX,IAAIvrB,KAAK+pB,iBAA0B,OAAPxC,IAAsB,MAAPA,IAAsB,MAAPA,GAC/D,MAAOvnB,MAAKmc,IAAI0P,yBACX,IAAW,MAAPtE,IAAqB,MAAPA,IAAqB,MAAPA,IAAqB,MAAPA,IAAqB,MAAPA,IAAcvnB,KAAK8rB,WACpF,MAAOvE,GAEP,MAAM,IAAIroB,OAAM,8BAKhB6sB,IAAI,SAASxtB,QAAQkB,OAAOJ,SAMlCI,OAAOJ,SACL2sB,qBAAsB,WACpB,GAAIzE,IAAKvnB,KAAK8mB,OACd,QAAOS,IACL,IAAK,IACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,OACH,MAAOvnB,MAAKqoB,cACd,KAAK,IACH,MAAOroB,MAAKsoB,WACd,KAAK,IACH,MAAiC,MAA7BtoB,KAAKiF,OAAOjF,KAAKmF,QACZnF,KAAKsoB,YAC0B,MAA7BtoB,KAAKiF,OAAOjF,KAAKmF,SAC1BnF,KAAK8mB,QACE9mB,KAAKuoB,iBAEPvoB,KAAKisB;AACd,IAAK,IACH,MAAOjsB,MAAKksB,4BACd,KAAK,IACH,MAAOlsB,MAAKmsB,kBACd,KAAK,IAEH,MADAnsB,MAAKsnB,MAAM,gBACJ,GACT,KAAK,IACH,IAAKtnB,KAAK8pB,YAAc9pB,KAAK0nB,SAAS,KAAM,CAC1C1nB,KAAK8mB,OACL,IAAIsF,QAASpsB,KAAKiF,OAAOjF,KAAKmF,OAK9B,OAJe,OAAXinB,QAA8B,OAAXA,QAAiBpsB,KAAK8mB,QACzC9mB,KAAKonB,eAAe7nB,OAAS,GAC/BS,KAAKsnB,MAAM,WAENtnB,KAAKmc,IAAIkQ,YAElB,MAAOrsB,MAAKisB,eACd,KAAK,IACH,MAAIjsB,MAAK8pB,YAA2C,MAA7B9pB,KAAKiF,OAAOjF,KAAKmF,SACtCnF,KAAK8mB,QACLS,GAAKvnB,KAAKiF,OAAOjF,KAAKmF,QACX,OAAPoiB,IAAsB,OAAPA,IACjBvnB,KAAK8mB,QAEP9mB,KAAK8pB,YAAa,EACd9pB,KAAKonB,eAAe7nB,OAAS,GAC/BS,KAAKsnB,MAAM,WAENtnB,KAAKmc,IAAIkQ,aAEXrsB,KAAKisB,eACd,KAAK,IAEH,MADAjsB,MAAKsnB,MAAM,mBACJ,GACT,KAAK,IAKH,MAJItnB,MAAKonB,eAAe7nB,OAAS,GAE/BS,KAAK6oB,WAEA,GACT,SACE,GAAW,MAAPtB,GAAY,CAEd,GADAA,GAAKvnB,KAAK8mB,QACN9mB,KAAK6qB,SACP,MAAO7qB,MAAKwqB,aAERjD,KAAIvnB,KAAKwnB,MAAM,GAGvB,GAAIxnB,KAAK6qB,SACP,MAAO7qB,MAAKwqB,aACP,IAAIxqB,KAAKqrB,iBACd,MAAOrrB,MAAKsrB,gBAAgBC,UACvB,IAAGvrB,KAAK8rB,WACb,MAAO9rB,MAAKisB,gBAGlB,KAAM,IAAI/sB,OACR,0BAA4BqoB,GAAK,aAAevnB,KAAKgnB,SAAW,YAAchnB,KAAKmF,OAAS;EAIhGkjB,aAAc,WACZ,KAAMroB,KAAKmF,OAASnF,KAAK+mB,MAAM,CAC7B,GAAIQ,IAAKvnB,KAAK8mB,OACd,IAAW,MAAPS,IAAqB,OAAPA,IAAsB,OAAPA,IAAsB,OAAPA,GAAhD,CAGAvnB,KAAKwnB,MAAM,EACX,QAEF,MAAOxnB,MAAKmc,IAAIkM,oBAIdiE,IAAI,SAAS/tB,QAAQkB,OAAOJ,SAMlCI,OAAOJ,SACL6sB,2BAA4B,WAE1B,IADA,GAAI3E,IACEvnB,KAAKmF,OAASnF,KAAK+mB,MAEvB,GADAQ,GAAKvnB,KAAK8mB,QACA,MAANS,GACFvnB,KAAK8mB,YACA,IAAU,KAANS,GACT,KAGJ,OAAOvnB,MAAKmc,IAAI+P,4BAGlBK,WAAY,WACV,GAAIC,QAASxsB,KAAKmF,MAClB,IACmC,MAAjCnF,KAAKiF,OAAOjF,KAAKmF,OAAS,IACM,MAA7BnF,KAAKiF,OAAOjF,KAAKmF,SACgB,MAAjCnF,KAAKiF,OAAOjF,KAAKmF,OAAS,GAC7B,CAIA,GAHAnF,KAAKmF,QAAU,EAGXnF,KAAKysB,cACP,KAAMzsB,KAAKmF,OAASnF,KAAK+mB,OACvB/mB,KAAKmF,SACAnF,KAAKysB,iBAOd,GAAIC,OAAQ1sB,KAAKiF,OAAOjF,KAAKmF,OAAS,EAQtC,IAPc,MAAVunB,OAA4B,MAAVA,MACpB1sB,KAAKmF,SAELunB,MAAQ,KAIN1sB,KAAKqrB,iBAAkB,CAEzB,IADA,GAAIsB,UAAW3sB,KAAKmF,OAAS,EACvBnF,KAAKmF,OAASnF,KAAK+mB,OACvB/mB,KAAKmF,SACAnF,KAAK4sB,cAIZ,GAAIC,SAAU7sB,KAAKiF,OAAOC,UAAUynB,SAAU3sB,KAAKmF,OAAS,EAC5D,MAAKunB,OAASA,QAAU1sB,KAAKiF,OAAOjF,KAAKmF,OAAS,MAC5CunB,OAAO1sB,KAAKmF,SAEqB,OAAjCnF,KAAKiF,OAAOjF,KAAKmF,OAAS,IAAgD,OAAjCnF,KAAKiF,OAAOjF,KAAKmF,OAAS,IAWrE,MATAnF,MAAK8sB,cAAgBD;AACrBF,SAAW3sB,KAAKmF,OAASqnB,OACzBxsB,KAAKmF,OAASqnB,OACdxsB,KAAK8nB,QAAQ6E,UACC,MAAVD,MACF1sB,KAAKsnB,MAAM,aAEXtnB,KAAKsnB,MAAM,cAENtnB,KAAKmc,IAAI4Q,iBAMxB,MADA/sB,MAAKmF,OAASqnB,QACP,GAETL,iBAAkB,WAEhB,IADA,GAAI5E,IACEvnB,KAAKmF,OAASnF,KAAK+mB,MAEvB,GADAQ,GAAKvnB,KAAK8mB,QACA,MAANS,GACFvnB,KAAK8mB,YACA,CAAA,GAAU,KAANS,GACT,KACK,IAAU,KAANA,GAAW,CAEpB,GADAA,GAAKvnB,KAAK8mB,QACC,KAANS,IAAavnB,KAAKqrB,iBAAkB,CACvCrrB,KAAKwnB,MAAM,EACX,OAEFxnB,KAAKwnB,MAAM,OACN,IAAU,KAAND,GAAW,CAEpB,GADAA,GAAKvnB,KAAK8mB,QACA,KAANS,GAAW,CACbvnB,KAAKwnB,MAAM,EACX,OAEFxnB,KAAKwnB,MAAM,IAGf,GAAU,KAAND,GACF,MAAOvnB,MAAKmc,IAAI+P,0BAEhB,IAAIc,QAAS,CAYb,OAXuB,MAAnBhtB,KAAKinB,OAAO,IAAiC,MAAnBjnB,KAAKinB,OAAO,KACxC+F,OAAS,GAEPhtB,KAAKinB,OAAO1nB,OAAS,GACvBS,KAAKkoB,YACHloB,KAAKmc,IAAI0P,0BACT7rB,KAAKinB,OAAO1nB,OAASytB,QAGzBhtB,KAAKwnB,MAAMxnB,KAAKinB,OAAO1nB,OAASytB,QAChChtB,KAAKsnB,MAAM,oBACJtnB,KAAKinB,QAKhBgG,YAAa,WAEX,GAAIjtB,KAAKiF,OAAOC,UAAUlF,KAAKmF,OAAS,EAAGnF,KAAKmF,OAAS,EAAInF,KAAK8sB,cAAcvtB,UAAYS,KAAK8sB,cAAe,CAC9G,GAAIvF,IAAKvnB,KAAKiF,OAAOjF,KAAKmF,OAAS,EAAInF,KAAK8sB,cAAcvtB,OAC1D,IAAW,OAAPgoB,IAAsB,OAAPA,IAAsB,MAAPA,GAChC,OAAO;CAGX,OAAO,GAGT2F,eAAgB,WAEd,GAAIltB,KAAKitB,cAIP,MAFAjtB,MAAK8nB,QAAQ9nB,KAAK8sB,cAAcvtB,QAChCS,KAAK6oB,WACE7oB,KAAKmc,IAAIgR,aAIlB,KADA,GAAI5F,IAAKvnB,KAAKiF,OAAOjF,KAAKmF,OAAS,GAC7BnF,KAAKmF,OAASnF,KAAK+mB,MACvB,GAAW,OAAPQ,IAAsB,OAAPA,IAEjB,GADAA,GAAKvnB,KAAK8mB,QACN9mB,KAAKitB,cAKP,MAJAjtB,MAAKwnB,MAAM,GAAGqB,WACd7oB,KAAKkoB,YACHloB,KAAKmc,IAAIgR,cAAentB,KAAK8sB,cAAcvtB,QAEtCS,KAAKmc,IAAI0P,8BAGlBtE,IAAKvnB,KAAK8mB,OAId,OAAO9mB,MAAKmc,IAAI0P,2BAGlBuB,gBAAiB,WAEf,GAAI7F,IAAKvnB,KAAK8mB,OACd,IAAI9mB,KAAKitB,cAGP,MAFAjtB,MAAK8nB,QAAQ9nB,KAAK8sB,cAAcvtB,OAAS,GACzCS,KAAK6oB,WACE7oB,KAAKmc,IAAIgR,aAGlB,MAAMntB,KAAKmF,OAASnF,KAAK+mB,MASvB,GAPW,OAAPQ,KACFA,GAAKvnB,KAAK8mB,QACC,OAAPS,IAAsB,OAAPA,KACjBA,GAAKvnB,KAAK8mB,UAIH,OAAPS,IAAsB,OAAPA,IAEjB,GADAA,GAAKvnB,KAAK8mB,QACN9mB,KAAKitB,cAKP,MAJAjtB,MAAKwnB,MAAM,GAAGqB,WACd7oB,KAAKkoB,YACHloB,KAAKmc,IAAIgR,cAAentB,KAAK8sB,cAAcvtB,QAEtCS,KAAKmc,IAAI0P,8BAEb,IAAW,MAAPtE,GAAY,CAErB,GADAA,GAAKvnB,KAAK8mB,QACC,MAAPS,GAGF,MADAvnB,MAAKsnB,MAAM,0BACPtnB,KAAKinB,OAAO1nB,OAAS,GACvBS,KAAKkoB,YAAYloB,KAAKmc,IAAIkR,2BAA4B;AACtDrtB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAI0P,2BAET7rB,KAAKmc,IAAIkR,0BAEb,IAAIrtB,KAAKqrB,iBAAkB,CAEhC,GAAIsB,UAAW3sB,KAAKmF,OAChBijB,KAAOpoB,KAAKstB,kBAChB,OAAIttB,MAAKinB,OAAO1nB,OAASS,KAAKmF,OAASwnB,SAAW,GAChD3sB,KAAKkoB,YAAYE,KAAMpoB,KAAKmF,OAASwnB,SAAW,GAChD3sB,KAAKwnB,MAAMxnB,KAAKmF,OAASwnB,SAAW,GAC7B3sB,KAAKmc,IAAI0P,2BAETzD,UAIN,IAAW,MAAPb,IAET,GADAA,GAAKvnB,KAAK8mB,QACC,MAAPS,GAGF,MADAvnB,MAAKsnB,MAAM,mBACPtnB,KAAKinB,OAAO1nB,OAAS,GACvBS,KAAKkoB,YAAYloB,KAAKmc,IAAIoR,aAAc,GACxCvtB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAI0P,4BAEhB7rB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAIoR,kBAIpBhG,IAAKvnB,KAAK8mB,OAKd,OAAO9mB,MAAKmc,IAAI0P,2BAGlByB,iBAAkB,WAGhB,GAFAttB,KAAKsrB,gBACL/D,GAAKvnB,KAAK8mB,QACA,KAANS,GAGF,MAFAvnB,MAAKwnB,MAAM,GACXxnB,KAAKsnB,MAAM,iBACJtnB,KAAKmc,IAAIyP,UACX,IAAW,MAAPrE,GAAY,CACrB,GAAqB,MAAjBvnB,KAAK8mB,QAMP,MALA9mB,MAAK8mB,QACD9mB,KAAKqrB,kBACPrrB,KAAKsnB,MAAM,2BAEbtnB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAIyP,UAEhB5rB,MAAKwnB,MAAM,OAGbxnB,MAAKwnB,MAAM,EAEZ,OAAOxnB,MAAKmc,IAAIyP,YAGnB4B,kBAAmB,WAEjB,GAAIjG,IAAKvnB,KAAK8mB;AACd,GAAW,MAAPS,GAAY,CAEd,GADAA,GAAKvnB,KAAK8mB,QACC,MAAPS,GAEF,MADAvnB,MAAKsnB,MAAM,0BACJtnB,KAAKmc,IAAIkR,0BACX,IAAIrtB,KAAKqrB,iBAAkB,CAChC,GAAIlP,KAAMnc,KAAKstB,kBACf,OAAOnR,UAEJ,IAAW,MAAPoL,IACT,GAAiC,MAA7BvnB,KAAKiF,OAAOjF,KAAKmF,QAEnB,MADAnF,MAAKsnB,MAAM,mBACJtnB,KAAKmc,IAAIoR,iBAEb,IAAW,MAAPhG,GAET,MADAvnB,MAAK6oB,WACE,GAIT,MAAM7oB,KAAKmF,OAASnF,KAAK+mB,MAAM,CAC7B,GAAW,OAAPQ,GACFvnB,KAAK8mB,YACA,CAAA,GAAW,MAAPS,GAAY,CACrBvnB,KAAKwnB,MAAM,GACXxnB,KAAK6oB,WACL7oB,KAAKkoB,YAAY,IAAK,EACtB,OACK,GAAW,MAAPX,GAAY,CAErB,GADAA,GAAKvnB,KAAK8mB,QACC,MAAPS,GAEF,MADAvnB,MAAKsnB,MAAM,0BACPtnB,KAAKinB,OAAO1nB,OAAS,GACvBS,KAAKkoB,YAAYloB,KAAKmc,IAAIkR,2BAA4B,GACtDrtB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAI0P,2BAET7rB,KAAKmc,IAAIkR,0BAEb,IAAIrtB,KAAKqrB,iBAAkB,CAEhC,GAAIsB,UAAW3sB,KAAKmF,OAChBijB,KAAOpoB,KAAKstB,kBAChB,OAAIttB,MAAKinB,OAAO1nB,OAASS,KAAKmF,OAASwnB,SAAW,GAChD3sB,KAAKkoB,YAAYE,KAAMpoB,KAAKmF,OAASwnB,SAAW,GAChD3sB,KAAKwnB,MAAMxnB,KAAKmF,OAASwnB,SAAW,GAC7B3sB,KAAKmc,IAAI0P,2BAETzD,KAGXpoB,KAAKwnB,MAAM,OACN,IAAW,MAAPD,GAAY,CAErB,GADAA,GAAKvnB,KAAK8mB;AACC,MAAPS,GAGF,MADAvnB,MAAKsnB,MAAM,mBACPtnB,KAAKinB,OAAO1nB,OAAS,GACvBS,KAAKkoB,YAAYloB,KAAKmc,IAAIoR,aAAc,GACxCvtB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAI0P,4BAEhB7rB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAIoR,aAGpBvtB,MAAKwnB,MAAM,IAEbD,GAAKvnB,KAAK8mB,QAEZ,MAAO9mB,MAAKmc,IAAI0P,2BAIlB4B,sBAAuB,WAErB,GAAIlG,IAAKvnB,KAAK8mB,OACd,IAAW,MAAPS,GAAY,CAEd,GADAA,GAAKvnB,KAAK8mB,QACC,MAAPS,GAEF,MADAvnB,MAAKsnB,MAAM,0BACJtnB,KAAKmc,IAAIkR,0BACX,IAAIrtB,KAAKqrB,iBAAkB,CAChC,GAAIlP,KAAMnc,KAAKstB,kBACf,OAAOnR,UAEJ,IAAW,MAAPoL,IACT,GAAiC,MAA7BvnB,KAAKiF,OAAOjF,KAAKmF,QAEnB,MADAnF,MAAKsnB,MAAM,mBACJtnB,KAAKmc,IAAIoR,iBAEb,IAAW,MAAPhG,GAET,MADAvnB,MAAK6oB,WACE,GAIT,MAAM7oB,KAAKmF,OAASnF,KAAK+mB,MAAM,CAC7B,GAAW,OAAPQ,GACFvnB,KAAK8mB,YACA,CAAA,GAAW,MAAPS,GAAY,CACrBvnB,KAAKwnB,MAAM,GACXxnB,KAAK6oB,WACL7oB,KAAKkoB,YAAY,IAAK,EACtB,OACK,GAAW,MAAPX,GAAY,CAErB,GADAA,GAAKvnB,KAAK8mB,QACC,MAAPS,GAEF,MADAvnB,MAAKsnB,MAAM,0BACPtnB,KAAKinB,OAAO1nB,OAAS,GACvBS,KAAKkoB,YAAYloB,KAAKmc,IAAIkR,2BAA4B,GACtDrtB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAI0P,2BAET7rB,KAAKmc,IAAIkR;AAEb,GAAIrtB,KAAKqrB,iBAAkB,CAEhC,GAAIsB,UAAW3sB,KAAKmF,OAChBijB,KAAOpoB,KAAKstB,kBAChB,OAAIttB,MAAKinB,OAAO1nB,OAASS,KAAKmF,OAASwnB,SAAW,GAChD3sB,KAAKkoB,YAAYE,KAAMpoB,KAAKmF,OAASwnB,SAAW,GAChD3sB,KAAKwnB,MAAMxnB,KAAKmF,OAASwnB,SAAW,GAC7B3sB,KAAKmc,IAAI0P,2BAETzD,KAGXpoB,KAAKwnB,MAAM,OACN,IAAW,MAAPD,GAAY,CAErB,GADAA,GAAKvnB,KAAK8mB,QACC,MAAPS,GAGF,MADAvnB,MAAKsnB,MAAM,mBACPtnB,KAAKinB,OAAO1nB,OAAS,GACvBS,KAAKkoB,YAAYloB,KAAKmc,IAAIoR,aAAc,GACxCvtB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAI0P,4BAGhB7rB,KAAKwnB,MAAM,GACJxnB,KAAKmc,IAAIoR,aAGhBhG,KAAIvnB,KAAKwnB,MAAM,IAErBD,GAAKvnB,KAAK8mB,QAEZ,MAAO9mB,MAAKmc,IAAI0P,iCAId6B,IAAI,SAASnvB,QAAQkB,OAAOJ,SAMlCI,OAAOJ,SACLksB,SAAU,WACR,GAAI1Z,OAAQ7R,KAAKinB,OAAOphB,cACpB8nB,GAAK3tB,KAAK8c,SAASjL,MACvB,KAAK8b,GACH,GAAc,UAAV9b,MACE7R,KAAK0nB,SAAS,UAChB1nB,KAAK8nB,QAAQ,GACb6F,GAAK3tB,KAAKmc,IAAIyR,cAEdD,GAAK3tB,KAAKmc,IAAI0R,YAIhB,IADAF,GAAK3tB,KAAKmc,IAAIoP,SACA,MAAV1Z,OAA2B,MAAVA,MAAe,CAClC,GAAI0V,IAAKvnB,KAAK8mB,MAAM,EACpB,IAAW,MAAPS,GACF,MAAOvnB,MAAKmsB,kBACP,IAAW,MAAP5E,GACT,MAAOvnB,MAAKksB,4BACH3E,KACTvnB,KAAKwnB,MAAM,GAKnB,MAAOmG;EAGT1B,cAAe,WACb,GAAI1E,IAAKvnB,KAAKiF,OAAOjF,KAAKmF,OAAS,GAC/B4N,GAAK/S,KAAK8tB,eAAevG,GAC7B,OAAIxU,IACKA,GAAGtR,MAAMzB,SAETA,KAAKinB,QAIhB6G,gBACEC,EAAK,WAEH,MADA/tB,MAAKmF,SACDnF,KAAKqrB,kBACPrrB,KAAKmF,SACLnF,KAAKsrB,gBACEtrB,KAAKmc,IAAIyP,aAEhB5rB,KAAKmF,SACE,MAGX6oB,IAAK,WACH,GAAIC,OAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAC7B,OAAc,MAAV8oB,OACFjuB,KAAKsnB,MAAM,2BAA2BR,QAC/B9mB,KAAKmc,IAAIiP,mBACG,MAAV6C,OACTjuB,KAAK8mB,QACE9mB,KAAKmc,IAAI+R,OACG,MAAVD,OACTjuB,KAAK8mB,QACE9mB,KAAKmc,IAAIgS,eAEX,KAETC,KAAM,WACJ,MAAOpuB,MAAKmc,IAAIkS,gBAElBC,IAAK,WACH,MAAiC,MAA7BtuB,KAAKiF,OAAOjF,KAAKmF,SACnBnF,KAAK8mB,QACE9mB,KAAKmc,IAAIoS,aAEX,KAETC,IAAK,WACH,MAAiC,MAA7BxuB,KAAKiF,OAAOjF,KAAKmF,SACnBnF,KAAK8mB,QACE9mB,KAAKmc,IAAIsS,gBAET,KAGXC,IAAK,WACH,GAAIC,SAAU3uB,KAAKmF,MAKnB,IAJAnF,KAAK8mB,QACD9mB,KAAKysB,eACPzsB,KAAK4uB,mBAAmB9H,QAEtB9mB,KAAKqrB,iBAAkB,CACzB,GAAIwD,OAAQ7uB,KAAKinB,OAAO1nB,MACxBS,MAAKsrB,eACL,IAAIwD,WAAY9uB,KAAKinB,OAAO/hB,UAAU2pB,MAAQ,GAAGhpB,cAC7CkpB,OAAS/uB,KAAK2lB,aAAamJ;AAC/B,GAAIC,SACF/uB,KAAK8mB,QACD9mB,KAAKysB,eACPzsB,KAAK4uB,mBAAmB9H,QAEW,MAAjC9mB,KAAKiF,OAAOjF,KAAKmF,OAAS,IAC5B,MAAO4pB,QAMb,MADA/uB,MAAKwnB,MAAMxnB,KAAKmF,OAASwpB,SAClB,KAETK,IAAK,WACH,GAAIf,OAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAC7B,OAAc,MAAV8oB,OACFjuB,KAAK8mB,QACE9mB,KAAKmc,IAAI8S,gBACG,MAAVhB,MAC4B,MAAjCjuB,KAAKiF,OAAOjF,KAAKmF,OAAS,IAC5BnF,KAAK8nB,QAAQ,GACN9nB,KAAKmc,IAAI+S,iBAEhBlvB,KAAK8mB,QACE9mB,KAAKmc,IAAIgT,YAGb,KAETC,IAAK,WACH,GAAInB,OAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAC7B,OAAc,MAAV8oB,OACFjuB,KAAK8mB,QACE9mB,KAAKmc,IAAIkT,OACG,MAAVpB,OACTjuB,KAAK8mB,QACE9mB,KAAKmc,IAAImT,cAEX,KAETC,IAAK,WACH,MAAiC,MAA7BvvB,KAAKiF,OAAOjF,KAAKmF,QACkB,MAAjCnF,KAAKiF,OAAOjF,KAAKmF,OAAS,IAC5BnF,KAAK8nB,QAAQ,GACN9nB,KAAKmc,IAAIqT,qBAEhBxvB,KAAK8mB,QACE9mB,KAAKmc,IAAIsT,gBAGb,KAETC,IAAK,WACH,MAAiC,MAA7B1vB,KAAKiF,OAAOjF,KAAKmF,SACnBnF,KAAK8mB,QACE9mB,KAAKmc,IAAIwT,YAEX,KAETC,IAAK,WACH,GAAI3B,OAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAC7B,OAAc,MAAV8oB,OACFA,MAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAAS,GACpB,MAAV8oB,OACFjuB,KAAK8nB,QAAQ,GACN9nB,KAAKmc,IAAI0T,YACG,MAAV5B,OACLjuB,KAAKusB,aACAvsB,KAAKmc,IAAI4Q,iBAGpB/sB,KAAK8mB;AACE9mB,KAAKmc,IAAI2T,OACG,MAAV7B,OACTjuB,KAAK8mB,QAC4B,MAA7B9mB,KAAKiF,OAAOjF,KAAKmF,SACnBnF,KAAK8mB,QACE9mB,KAAKmc,IAAI4T,aAET/vB,KAAKmc,IAAI6T,uBAEC,MAAV/B,OACTjuB,KAAK8mB,QACE9mB,KAAKmc,IAAIsT,gBAEX,KAETQ,IAAK,WACH,GAAIhC,OAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAC7B,OAAc,MAAV8oB,OACFjuB,KAAK8mB,QACE9mB,KAAKmc,IAAI+T,uBACG,MAAVjC,OACTA,MAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAAS,GACpB,MAAV8oB,OACFjuB,KAAK8nB,QAAQ,GACN9nB,KAAKmc,IAAIgU,aAEhBnwB,KAAK8mB,QACE9mB,KAAKmc,IAAIiU,OAGb,KAETC,IAAK,WACH,GAAIpC,OAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAC7B,OAAc,MAAV8oB,OACFjuB,KAAK8mB,QACE9mB,KAAKmc,IAAImU,aACE,MAAVrC,OACRjuB,KAAK8mB,QAC4B,MAA7B9mB,KAAKiF,OAAOjF,KAAKmF,SACnBnF,KAAK8mB,QACE9mB,KAAKmc,IAAIoU,aAETvwB,KAAKmc,IAAIqU,OAGb,KAETC,IAAK,WACH,GAAIxC,OAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAC7B,OAAc,MAAV8oB,OACFjuB,KAAK8mB,QACE9mB,KAAKmc,IAAIuU,gBACG,MAAVzC,OAAkD,MAAjCjuB,KAAKiF,OAAOjF,KAAKmF,OAAS,IACpDnF,KAAK8nB,QAAQ,GACN9nB,KAAKmc,IAAIwU,YAEX,KAETC,IAAK,WACH,MAAiC,MAA7B5wB,KAAKiF,OAAOjF,KAAKmF,SACnBnF,KAAK8mB,QACE9mB,KAAKmc,IAAI0U,aAEX,KAETC,IAAK,WACH,GAAI7C,OAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAC7B,OAAc,MAAV8oB,OACFjuB,KAAK8mB;AACE9mB,KAAKmc,IAAI4U,aACG,MAAV9C,OACTjuB,KAAK8mB,QACE9mB,KAAKmc,IAAI6U,eAEX,KAETC,IAAK,WACH,GAAIhD,OAAQjuB,KAAKiF,OAAOjF,KAAKmF,OAC7B,OAAc,MAAV8oB,OACFjuB,KAAK8mB,QACE9mB,KAAKmc,IAAI+U,YACG,MAAVjD,OACTjuB,KAAK8mB,QACE9mB,KAAKmc,IAAIgV,cAEX,KAETC,IAAK,WACH,MAAiC,MAA7BpxB,KAAKiF,OAAOjF,KAAKmF,SACnBnF,KAAK8mB,QACE9mB,KAAKmc,IAAIkV,aAEX,YAKPC,IAAI,SAAS/yB,QAAQkB,OAAOJ,SAMjC,GAAI+c,QAAS,4BAEd3c,QAAOJ,SAGLwrB,OAAQ,WACN,GAAItD,IAAKvnB,KAAKiF,OAAOssB,WAAWvxB,KAAKmF,OAAS,EAC9C,OAAOoiB,IAAK,IAAMA,GAAK,IAIzBqF,SAAU,WACR,GAAIrF,IAAKvnB,KAAKiF,OAAOssB,WAAWvxB,KAAKmF,OAAS,EAC9C,OAAQoiB,IAAK,IAAMA,GAAK,KAClBA,GAAK,IAAMA,GAAK,IACV,KAAPA,IACCA,GAAK,IAAMA,GAAK,IACjBA,GAAK,KAKZ8D,eAAgB,WACd,GAAI9D,IAAKvnB,KAAKiF,OAAOssB,WAAWvxB,KAAKmF,OAAS,EAC9C,OAAQoiB,IAAK,IAAMA,GAAK,KAClBA,GAAK,IAAMA,GAAK,IACV,KAAPA,IACCA,GAAK,KAMb+D,cAAe,WACb,KAAMtrB,KAAKmF,OAASnF,KAAK+mB,MAEvB,GADA/mB,KAAK8mB,SACA9mB,KAAK4sB,WAAY,CACpB5sB,KAAKwnB,MAAM,EACX,OAGJ,MAAOxnB,OAIT8rB,SAAU,WACR,GAAIvE,IAAKvnB,KAAKiF,OAAOjF,KAAKmF,OAAS,EACnC,OAAOiX,QAAOoV,QAAQjK,OAAQ,GAGhCwC,cAAe,WACb,GAAIxC,IAAKvnB,KAAKiF,OAAOjF,KAAKmF,OAAS;AACnC,MAAc,MAAPoiB,IAAqB,OAAPA,IAAsB,OAAPA,IAAsB,OAAPA,IAGrDkF,YAAa,WACX,GAAIlF,IAAKvnB,KAAKiF,OAAOjF,KAAKmF,OAAS,EACnC,OAAc,MAAPoiB,IAAqB,OAAPA,IAGvBqH,iBAAkB,WAChB,KAAM5uB,KAAKmF,OAASnF,KAAK+mB,MAEvB,GADA/mB,KAAK8mB,SACA9mB,KAAKysB,cAAe,CACvBzsB,KAAKwnB,MAAM,EACX,OAGJ,MAAOxnB,OAGT0qB,OAAQ,WACN,GAAInD,IAAKvnB,KAAKiF,OAAOssB,WAAWvxB,KAAKmF,OAAS,EAC9C,OAAQoiB,IAAK,IAAMA,GAAK,IAAQA,GAAK,IAAMA,GAAK,IAAQA,GAAK,IAAMA,GAAK,WAItEkK,KAAK,SAASlzB,QAAQkB,OAAOJ,SAUnC,QAASqyB,UAAShzB,GAChB,MAAY,KAALA,GAAiB,KAALA,IAAaizB,MAAMC,WAAWlzB,KAAOmzB,SAASnzB,GAcnE,GAAI0E,QAAS,SAASC,MAAOyuB,KAC3B9xB,KAAKqD,MAAQA,MACbrD,KAAK8xB,IAAMA,IACX9xB,KAAKmc,IAAM9Y,MAAM8Y,IACjBnc,KAAKsc,IAAMjZ,MAAMiZ,IACjBtc,KAAK6R,MAAQ,KACb7R,KAAK+xB,KAAO,KACZ/xB,KAAKuc,OAAQ,EACbvc,KAAKgyB,YAAa,EAClBhyB,KAAKiyB,gBAAiB,EACtBjyB,KAAKkyB,SACHC,UACEnyB,KAAKmc,IAAIyP,WACT,IAAK,IACL5rB,KAAKmc,IAAIkS,eACTruB,KAAKmc,IAAIoP,SACTvrB,KAAKmc,IAAImH,YACTtjB,KAAKmc,IAAIiI,UAEXgO,QACEpyB,KAAKmc,IAAI+P,2BACTlsB,KAAKmc,IAAI4Q,gBACT/sB,KAAKmc,IAAI6O,UACThrB,KAAKmc,IAAI4O,UACT/qB,KAAKmc,IAAI+I,QAAQ,IACjBllB,KAAKmc,IAAIa,UACThd,KAAKmc,IAAIe,UACTld,KAAKmc,IAAIiB,SACTpd,KAAKmc,IAAImB,WACTtd,KAAKmc,IAAIqB,OACTxd,KAAKmc,IAAIuB,OACT1d,KAAKmc,IAAIyB,MACT5d,KAAKmc,IAAI2B,OACT,IACA,KACA,KACA,IACA9d,KAAKmc,IAAIkS;AAEXgE,eACIryB,KAAKmc,IAAIa,UACThd,KAAKmc,IAAIe,UACTld,KAAKmc,IAAIiB,SACTpd,KAAKmc,IAAImB,WACTtd,KAAKmc,IAAIqB,OACTxd,KAAKmc,IAAIuB,OACT1d,KAAKmc,IAAIyB,MACT5d,KAAKmc,IAAI2B,QAEbwU,gBACEtyB,KAAKmc,IAAI2I,SACT9kB,KAAKmc,IAAIuI,UACT1kB,KAAKmc,IAAIyI,YACT5kB,KAAKmc,IAAIiI,SACTpkB,KAAKmc,IAAImI,WACTtkB,KAAKmc,IAAIqI,SAEX+N,KACE,IACAvyB,KAAKmc,IAAIkQ,YACTrsB,KAAKsc,IACLtc,KAAKmc,IAAIgO,eAEXqI,MACE,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IACxBxyB,KAAKmc,IAAI8I,OACTjlB,KAAKmc,IAAIsG,QACTziB,KAAKmc,IAAIkT,MACTrvB,KAAKmc,IAAI+R,MACTluB,KAAKmc,IAAIoG,MACTviB,KAAKmc,IAAI2H,QACT9jB,KAAKmc,IAAI6H,QACThkB,KAAKmc,IAAI4G,UACT/iB,KAAKmc,IAAI8G,eACTjjB,KAAKmc,IAAI+G,UACTljB,KAAKmc,IAAIiH,eACTpjB,KAAKmc,IAAI0G,OACT7iB,KAAKmc,IAAI0J,WACT7lB,KAAKmc,IAAI6J,cACThmB,KAAKmc,IAAIiK,cACTpmB,KAAKmc,IAAImK,aACTtmB,KAAKmc,IAAIqK,cACTxmB,KAAKmc,IAAIuK,YACT1mB,KAAKmc,IAAIyK,aACT5mB,KAAKmc,IAAI6B,OACThe,KAAKmc,IAAI2F,QACT9hB,KAAKmc,IAAI0R,QACT7tB,KAAKmc,IAAIiI,SACTpkB,KAAKmc,IAAIgC,WAETne,KAAKmc,IAAIyP,WACT,IACA5rB,KAAKmc,IAAIkS,eACTruB,KAAKmc,IAAIoP,SAETvrB,KAAKmc,IAAIoP,SACTvrB,KAAKmc,IAAI+P,2BACTlsB,KAAKmc,IAAI4Q,gBACT/sB,KAAKmc,IAAI6O,UACThrB,KAAKmc,IAAI4O,UACT/qB,KAAKmc,IAAI+I,QAAQ,IACjBllB,KAAKmc,IAAIa,UACThd,KAAKmc,IAAIe,UACTld,KAAKmc,IAAIiB,SACTpd,KAAKmc,IAAImB,WACTtd,KAAKmc,IAAIqB,OACTxd,KAAKmc,IAAIuB,OACT1d,KAAKmc,IAAIyB,MACT5d,KAAKmc,IAAI2B;EAQf1a,QAAO5B,UAAUixB,aAAe,SAAS5gB,OACvC,MAAK6f,UAAS7f,OAGRA,OAAS7R,KAAKsc,IAAY,wBACvBtc,KAAKqD,MAAM6Y,OAAOE,OAAO4M,OAAOnX,OAHhC,IAAMA,MAAQ,KAUzBzO,OAAO5B,UAAUkxB,MAAQ,SAASvzB,KAAMwzB,UACtC3yB,KAAK4yB,WACL5yB,KAAK2yB,SAAWA,UAAY,OAC5B3yB,KAAK6yB,kBAAoB,IACzB7yB,KAAKqD,MAAMwjB,SAAS1nB,MACpBa,KAAKqD,MAAMoZ,eAAiBzc,KAAKgyB,WACjChyB,KAAKT,OAASS,KAAKqD,MAAM4B,OAAO1F,OAChCS,KAAK8yB,WAAY,CACjB,IAAIC,SAAU/yB,KAAK8xB,IAAIntB,QAAQ,UAAW3E,MACtCgzB,SAEJ,KADAhzB,KAAKizB,mBACCjzB,KAAK6R,OAAS7R,KAAKsc,KAAK,CAC5B,GAAI9W,MAAOxF,KAAKkzB,YACH,QAAT1tB,MAA0B2tB,SAAT3tB,OACfnE,MAAM+xB,QAAQ5tB,MAChBwtB,OAASA,OAAOvyB,OAAO+E,MAEvBwtB,OAAOzxB,KAAKiE,OAIlB,MAAOutB,SAAQC,OAAQhzB,KAAK4yB,UAM9BxvB,OAAO5B,UAAU6xB,WAAa,SAASzhB,QAAS0hB,UAAWC,OAAQ1hB,OAEjE,GADAD,SAAW,YAAc5R,KAAKqD,MAAMC,OAAOC,YACtCvD,KAAKiyB,eAAgB,CACxB,GAAIuB,KAAM,GAAIC,aACZ7hB,QAAS5R,KAAK2yB,SAAU3yB,KAAKqD,MAAMC,OAAOC,WAK5C,MAHAiwB,KAAIE,WAAa1zB,KAAKqD,MAAMC,OAAOC,WACnCiwB,IAAIG,SAAW3zB,KAAK2yB,SACpBa,IAAII,aAAe5zB,KAAKqD,MAAMC,OAAOE,aAC/BgwB,IAGR,GAAIhuB,MAAOxF,KAAK8xB,IAAIntB,QAAQ,QAAS3E,MACnC4R,QAASC,MAAO7R,KAAKqD,MAAMC,OAAOC,WAAYgwB;AAGhD,MADAvzB,MAAK4yB,QAAQrxB,KAAKiE,MACXA,MAMTpC,OAAO5B,UAAUqyB,MAAQ,SAASN,QAChC,GAAIO,KAAM,4BAEV,IADAjiB,MAAQ7R,KAAKyyB,aAAazyB,KAAK6R,OAC3B7R,KAAK6R,QAAU7R,KAAKsc,IAAK,CAC3B,GAAIoV,SAAS1xB,KAAK6R,OAAQ,CACxB,GAAIkiB,QAAS/zB,KAAK2nB,MACdoM,QAAOx0B,OAAS,KAClBw0B,OAASA,OAAO7uB,UAAU,EAAG,GAAK,OAEpC2M,MAAQ,IAAKkiB,OAAO,MAAOliB,MAAM,IAEnCiiB,KAAO,gBAAkBjiB,MAE3B,GAAIyhB,WAAY,EAQhB,OAPIC,UAAWlyB,MAAM+xB,QAAQG,WACvB7B,SAAS6B,SAA6B,IAAlBA,OAAOh0B,UAC7B+zB,UAAY,eAAiBtzB,KAAKyyB,aAAac,SAEjDO,KAAOR,WAETtzB,KAAK6R,QAAU7R,KAAKsc,IACbtc,KAAKqzB,WACVS,IACAR,UACAC,OACA1hB,QAOJzO,OAAO5B,UAAUgE,KAAO,SAAShD,MAC/B,MAAOxC,MAAK8xB,IAAIntB,QAAQnC,KAAMxC,OAOhCoD,OAAO5B,UAAUwyB,qBAAuB,WACtC,GAAmB,MAAfh0B,KAAK6R,MACP7R,KAAKizB,mBACDjzB,KAAK6R,QAAU7R,KAAKmc,IAAIkQ,aAE1BrsB,KAAKizB,uBAEF,IAAIjzB,KAAK6R,QAAU7R,KAAKmc,IAAIkQ,YACjCrsB,KAAKizB,uBACA,IAAIjzB,KAAK6R,QAAU7R,KAAKmc,IAAIgO,eAAiBnqB,KAAK6R,QAAU7R,KAAKsc,IAEtE,MADAtc,MAAK6zB,MAAM,MACJ,CAET,QAAO,EAIT,IAAII,cAAe,cAAe,wBAAyB;AAC3D7wB,OAAO5B,UAAU0yB,QAAU,WAGzB,IAAK,GADDpiB,MADAqX,OAAQ,GAAKjqB,QAASiqB,MAAMgL,MAAM,MAE7BhvB,OAAS,EAAGA,OAASgkB,MAAM5pB,OAAQ4F,SAAW,CACrD2M,KAAOqX,MAAMhkB,QAAQivB,MAErB,KAAI,GADAC,QAAQ,EACJr1B,EAAI,EAAGA,EAAIi1B,YAAY10B,OAAQP,IACrC,GAAI8S,KAAK5M,UAAU,EAAG,EAAI+uB,YAAYj1B,GAAGO,UAAY00B,YAAYj1B,GAAI,CACnEq1B,OAAQ,CACR,OAGJ,IAAKA,MACH,MAYJ,MARApL,SAAQC,IACN,QACElpB,KAAKqD,MAAMC,OAAOC,WAClB,MACAvD,KAAKyyB,aAAazyB,KAAK6R,OACvB,IAAM7R,KAAKqD,MAAM4jB,OAAS,SAChBnV,MAEP9R,MAgBToD,OAAO5B,UAAU+xB,OAAS,SAAS1hB,OACjC,GAAIxQ,MAAM+xB,QAAQvhB,QAChB,GAAIA,MAAM2f,QAAQxxB,KAAK6R,UAAW,EAEhC,MADA7R,MAAK6zB,MAAMhiB,QACJ,MAEJ,IAAI7R,KAAK6R,OAASA,MAEvB,MADA7R,MAAK6zB,MAAMhiB,QACJ,CAET,QAAO,GAOTzO,OAAO5B,UAAUmmB,KAAO,WACtB,MAAO3nB,MAAKqD,MAAM4jB,QAIpB7jB,OAAO5B,UAAU4mB,KAAO,WAStB,MARIpoB,MAAKuc,OACPvc,KAAKk0B,UACLl0B,KAAKuc,OAAQ,EACbvc,KAAKizB,mBAAmBqB,iBACxBt0B,KAAKuc,OAAQ,GAEbvc,KAAKizB,mBAAmBqB,iBAEnBt0B,MAIToD,OAAO5B,UAAU8yB,eAAiB,WAEhC,IADIt0B,KAAKuc,OAAOvc,KAAKk0B,UACfl0B,KAAK6R,QAAU7R,KAAKmc,IAAImM,WAAatoB,KAAK6R,QAAU7R,KAAKmc,IAAIoM,eAEjEvoB,KAAKizB;AAEP,MAAOjzB,OAIToD,OAAO5B,UAAUyxB,iBAAmB,WAQlC,MAPAjzB,MAAK+xB,MACH/xB,KAAKqD,MAAMC,OAAOC,WAClBvD,KAAKqD,MAAMC,OAAOE,aAClBxD,KAAKqD,MAAM8B,QAEbnF,KAAK6R,MAAQ7R,KAAKqD,MAAM8kB,OAASnoB,KAAKsc,IAClCtc,KAAKuc,OAAOvc,KAAKk0B,UACdl0B,MAMToD,OAAO5B,UAAU+yB,GAAK,SAASlwB,MAC7B,MAAIhD,OAAM+xB,QAAQ/uB,MACTA,KAAKmtB,QAAQxxB,KAAK6R,UAAW,EAE7B7R,KAAKkyB,QAAQ7tB,MAAMmtB,QAAQxxB,KAAK6R,SAAU,IAMnDtT,QAAQ,qBACRA,QAAQ,qBACRA,QAAQ,uBACRA,QAAQ,oBACRA,QAAQ,wBACRA,QAAQ,kBACRA,QAAQ,qBACRA,QAAQ,oBACRA,QAAQ,yBACRA,QAAQ,sBACRA,QAAQ,yBACRA,QAAQ,sBACRA,QAAQ,mBACRA,QAAQ,qBACRA,QAAQ,yBACRoF,QAAQ,SAAUoK,KAClB,IAAI,GAAIqb,KAAKrb,KACX3K,OAAO5B,UAAU4nB,GAAKrb,IAAIqb,KAI9B3pB,OAAOJ,QAAU+D,SAEdoxB,oBAAoB,IAAIC,oBAAoB,IAAIC,sBAAsB,IAAIC,mBAAmB,IAAIC,uBAAuB;AAAIC,iBAAiB,IAAIC,oBAAoB,IAAIC,mBAAmB,IAAIC,wBAAwB,IAAIC,qBAAqB,IAAIC,wBAAwB,IAAIC,qBAAqB,IAAIC,kBAAkB,IAAIC,oBAAoB,IAAIC,uBAAuB,MAAMC,KAAK,SAASh3B,QAAQkB,OAAOJ,SAMrZ,GAAIm2B,WAAY,QACZC,WAAa,OAEjBh2B,QAAOJ,SAQLq2B,WAAY,WACV,GAAInC,QAAS,KACT7nB,WAAY,EACZC,SACA3H,OAAShE,KAAKwF,KAAKgwB,UAUvB,IARIx1B,KAAK6R,QAAU7R,KAAKmc,IAAI+I,SAC1BllB,KAAKooB,OAAOmL,OAAO,KACnBA,OAAS,MAET7nB,WAAY,EACZ6nB,OAAS,KAGPvzB,KAAKooB,OAAOvW,OAAS0hB,OACvB,KAAMvzB,KAAK6R,OAAS7R,KAAKsc,MACvB3Q,MAAMpK,KAAKvB,KAAK21B,wBACE,KAAd31B,KAAK6R,SACP7R,KAAKooB,OACDpoB,KAAK6R,QAAU0hB,UAQzB,MAFAvzB,MAAKuzB,OAAOA,QACZvzB,KAAKooB,OACEpkB,OAAO0H,UAAWC,QAe3BgqB,qBAAsB,WACpB,GAAI3xB,QAAShE,KAAKwF,KAAKiwB,YACnB/jB,IAAM,KACN/E,MAAQ,IACZ,IAAmB,MAAf3M,KAAK6R,MACPlF,MAAQ3M,KAAKooB,OAAOwN,eAAc,GAAM,GAAO,OAC1C,CACL,GAAInd,MAAOzY,KAAK61B,WACZ71B,MAAK6R,QAAU7R,KAAKmc,IAAI8S,gBAC1Bvd,IAAM+G,KAEJ9L,MADwB,MAAtB3M,KAAKooB,OAAOvW,MACN7R,KAAKooB,OAAOwN,eAAc,GAAM,GAAO,GAEvC51B,KAAK61B,aAGflpB,MAAQ8L;CAGZ,MAAOzU,QAAO0N,IAAK/E,QAOrBmpB,gBAAiB,WACf,MAAkB,KAAd91B,KAAK6R,OACF7R,KAAK61B,mBAIVE,KAAK,SAASx3B,QAAQkB,OAAOJ,SAOnCI,OAAOJ,SAOL22B,WAAY,SAASC,MACnB,GAAIjyB,QAAShE,KAAKwF,KAAK,QACvBxF,MAAKuzB,OAAOvzB,KAAKmc,IAAI6F,SACrBhiB,KAAKooB,OAAOmL,OAAOvzB,KAAKmc,IAAIoP,SAC5B,IAGIje,MAHA4oB,SAAWl2B,KAAK2nB,OAChBwO,YAAc,KACdC,eAAiB,IAWrB,OARIp2B,MAAKooB,OAAOvW,OAAS7R,KAAKmc,IAAIiG,YAChC+T,YAAcn2B,KAAKooB,OAAOiO,uBAExBr2B,KAAK6R,OAAS7R,KAAKmc,IAAIkG,eACzB+T,eAAiBp2B,KAAKooB,OAAOkO,kBAE/Bt2B,KAAKuzB,OAAO,KACZjmB,KAAOtN,KAAKizB,mBAAmBsD,kBACxBvyB,OACLkyB,SACCC,YACAC,eACA9oB,KACA2oB,OASJO,iBAAkB,WACjB,GAAIxyB,QAAShE,KAAK6R,KAClB,OAAI7N,SAAUhE,KAAKmc,IAAIqI,SACrBxkB,KAAKooB,QACG,EAAG,EAAG,IACLpkB,QAAUhE,KAAKmc,IAAImI,YAC5BtkB,KAAKooB,QACG,EAAG,EAAG,KAER,EAAG,EAAG,IAQfmO,gBAAiB,WAGhB,IAFA,GAAIvyB,WAEEhE,KAAK6R,QAAU7R,KAAKsc,KAAsB,MAAftc,KAAK6R,OAEpC,GAAI7R,KAAK6R,QAAU7R,KAAKmc,IAAImM,UAK5B,GAAItoB,KAAK6R,QAAU7R,KAAKmc,IAAIoM,cAM5B,GAAIvoB,KAAK6R,QAAU7R,KAAKmc,IAAIqH,MAA5B,CAQA,GAAIvV,OAAQjO,KAAKy2B,mBAAkB;AAGnC,GAAIz2B,KAAK6R,QAAU7R,KAAKmc,IAAIkC,QAc5B,GALIre,KAAK6R,QAAU7R,KAAKmc,IAAIwG,QAC1B3iB,KAAKooB,OAAOmL,OAAOvzB,KAAKmc,IAAIyP,YAC5B3d,MAAM,GAAKA,MAAM,GAAK,GAGpBjO,KAAK6R,QAAU7R,KAAKmc,IAAIyP,WAAY,CAGtC,GAAI8K,WAAY12B,KAAK22B,mBAAmB1oB,MACxCjO,MAAKuzB,OAAO,KACZvzB,KAAKizB,mBACLjvB,OAASA,OAAOvD,OAAOi2B,eAEd12B,MAAK6R,QAAU7R,KAAKmc,IAAIgC,WAGjCna,OAAOzC,KAAKvB,KAAK42B,eAAc,EAAO3oB,SAKtCjO,KAAK6zB,OACH7zB,KAAKmc,IAAIkC,QACTre,KAAKmc,IAAIyP,WACT5rB,KAAKmc,IAAIgC,aAGXne,KAAKooB,YApCP,CACE,GAAIyO,WAAY72B,KAAK82B,mBAAmB7oB,MACxCjO,MAAKuzB,OAAO,KACZvzB,KAAKizB,mBACLjvB,OAASA,OAAOvD,OAAOo2B,gBAdvB7yB,QAASA,OAAOvD,OACdT,KAAKooB,OAAO2O,gCAPd/yB,QAAOzC,KAAKvB,KAAKg3B,wBALjBhzB,QAAOzC,KAAKvB,KAAKi3B,eA+DrB,OAFAj3B,MAAKuzB,OAAO,KACZvzB,KAAKizB,mBACEjvB,QAQR2yB,mBAAoB,SAAS1oB,OAC5B,MAAOjO,MAAKk3B,UAQV,QAASC,6BACP,GAAInzB,QAAShE,KAAKwF,KAAK,WACvBxF,MAAKuzB,OAAOvzB,KAAKmc,IAAIyP,WACrB,IAAIppB,MAAOxC,KAAK2nB,OAAOziB,UAAU,EAEjC,OADAlF,MAAKooB,OACc,MAAfpoB,KAAK6R,OAAgC,MAAf7R,KAAK6R,MACtB7N,OAAOxB,KAAM,KAAMyL,OACH,MAAfjO,KAAK6R,MAEN7N,OAAOxB,KAAMxC,KAAKooB,OAAOyN,YAAa5nB,QAE7CjO,KAAKuzB,QAAQ,IAAK,IAAK;AAChBvvB,OAAOxB,KAAM,KAAMyL,SAE3B,MASN6oB,mBAAoB,SAAS7oB,OAI5B,MAHIjO,MAAKuzB,OAAOvzB,KAAKmc,IAAIkC,UACvBre,KAAKooB,OAEApoB,KAAKk3B,UASR,QAASE,6BACP,GAAIpzB,QAAShE,KAAKwF,KAAK,iBAAkBhD,KAAO,KAAMmK,MAAQ,IAQ9D,OAPI3M,MAAKuzB,OAAOvzB,KAAKmc,IAAIoP,YACvB/oB,KAAOxC,KAAK2nB,OACZ3nB,KAAKooB,QAEHpoB,KAAKuzB,OAAO,OACd5mB,MAAS3M,KAAKooB,OAAOyN,aAEhB7xB,OAAOxB,KAAMmK,MAAOsB,QAC1B,MAWRwoB,kBAAmB,SAASY,aAC3B,GAAIrzB,UAAU,GAAI,GAAI,EACtB,IAAIhE,KAAKu0B,GAAG,kBAAmB,CAC7B,GAAI+C,KAAM,EAAGC,IAAM,CACnB,GAAG,CACD,OAAOv3B,KAAK6R,OACV,IAAK7R,MAAKmc,IAAI2I,SAAcwS,IAAM,EAAGC,IAAM,CAAG,MAC9C,KAAKv3B,MAAKmc,IAAIyI,YAAc0S,IAAM,EAAGC,IAAM,CAAG,MAC9C,KAAKv3B,MAAKmc,IAAIuI,UAAc4S,IAAM,EAAGC,IAAM,CAAG,MAC9C,KAAKv3B,MAAKmc,IAAIiI,SAAckT,IAAM,EAAGC,IAAM,CAAG,MAC9C,KAAKv3B,MAAKmc,IAAImI,WAAcgT,IAAM,EAAGC,IAAM,CAAG,MAC9C,KAAKv3B,MAAKmc,IAAIqI,QAAc8S,IAAM,EAAGC,IAAM,EAEzCF,cACS,GAAPC,KAAmB,GAAPC,KAEdv3B,KAAKuzB,QAAQvzB,KAAKmc,IAAI2I,SAAU9kB,KAAKmc,IAAIyI,cACzC2S,KAAM,GACU,GAAPD,KAAmB,GAAPC,MAErBv3B,KAAK6zB,QACL0D,KAAM,IAGNvzB,OAAOszB,QAAS,EAElBt3B,KAAK6zB,QACI0D,OAAQ,IACjBvzB,OAAOszB,KAAOC,WAEVv3B,KAAKooB,OAAOmM,GAAG,mBAMzB,MAHIvwB,QAAO,KAAM,IAAIA,OAAO,GAAK,GAC7BA,OAAO,KAAM,IAAIA,OAAO,GAAK;AAC7BA,OAAO,KAAM,IAAIA,OAAO,GAAK,GAC1BA,QAQRwzB,eAAgB,WACf,GAAIxzB,QAAShE,KAAKwF,KAAK,aAAchD,KAAO,KAAM8K,KAAO,KAAM6oB,YAAc,IAc7E,OAbIn2B,MAAKuzB,OAAOvzB,KAAKmc,IAAI+F,cACvBliB,KAAKooB,OAEHpoB,KAAKuzB,OAAOvzB,KAAKmc,IAAIoP,YACvB/oB,KAAOxC,KAAK2nB,OACZ3nB,KAAKooB,QAEHpoB,KAAK6R,QAAU7R,KAAKmc,IAAIiG,YAC1B+T,YAAcn2B,KAAKooB,OAAOkO,kBAExBt2B,KAAKuzB,OAAO,OACdjmB,KAAOtN,KAAKooB,OAAOqP,uBAEdzzB,OAAOxB,KAAM2zB,YAAa7oB,OAQlCmqB,oBAAqB,WAGpB,IAFA,GAAIzzB,WAEEhE,KAAK6R,QAAU7R,KAAKsc,KAAsB,MAAftc,KAAK6R,OAEpC,GAAI7R,KAAK6R,QAAU7R,KAAKmc,IAAImM,UAK5B,GAAItoB,KAAK6R,QAAU7R,KAAKmc,IAAIoM,cAA5B,CAMA,GAAIta,OAAQjO,KAAKy2B,mBAAkB,EAGnC,IAAIz2B,KAAK6R,OAAS7R,KAAKmc,IAAIkC,QAAS,CAClC,GAAIwY,WAAY72B,KAAK82B,mBAAmB7oB,MACpCjO,MAAKuzB,OAAO,MACdvzB,KAAKizB,mBAEPjvB,OAASA,OAAOvD,OAAOo2B,eAIpB,IAAI72B,KAAK6R,QAAU7R,KAAKmc,IAAIgC,WAAY,CAC3C,GAAIrE,QAAS9Z,KAAK03B,0BAA0B,EAAGzpB,MAC/C6L,QAAO1L,WAAWH,OAClBjK,OAAOzC,KAAKuY,QACR9Z,KAAKuzB,OAAO,MACdvzB,KAAKizB,uBAIPjzB,MAAK6zB,OACH7zB,KAAKmc,IAAIkC,QACTre,KAAKmc,IAAIgC,aAEXne,KAAKooB,WA9BLpkB,QAAOzC,KAAKvB,KAAKg3B,wBALjBhzB,QAAOzC,KAAKvB,KAAKi3B;AAyCrB,MAHIj3B,MAAKuzB,OAAO,MACdvzB,KAAKooB,OAEApkB,QAQR2zB,WAAY,SAAS1B,MACpB,GAAIjyB,QAAShE,KAAKwF,KAAK,SACrB0wB,SAAW,KACXC,YAAc,KACdC,eAAiB,KACjB9oB,KAAO,IAgBT,OAfItN,MAAKuzB,OAAOvzB,KAAKmc,IAAIgG,UACvBniB,KAAKooB,OAEHpoB,KAAKuzB,OAAOvzB,KAAKmc,IAAIoP,YACvB2K,SAAWl2B,KAAK2nB,QAEd3nB,KAAKooB,OAAOvW,OAAS7R,KAAKmc,IAAIiG,YAChC+T,YAAcn2B,KAAKooB,OAAOiO,uBAExBr2B,KAAK6R,OAAS7R,KAAKmc,IAAIkG,eACzB+T,eAAiBp2B,KAAKooB,OAAOkO,kBAE3Bt2B,KAAKuzB,OAAO,OACdjmB,KAAOtN,KAAKooB,OAAOmO,mBAEdvyB,OACLkyB,SACAC,YACAC,eACA9oB,OASHypB,yBAA0B,WAKzB,IAHA,GAAIvxB,MAAOxF,KAAKwF,KAAK,YACjB6U,QAAUra,KAAKq2B,uBACf/b,YAAc,KACG,MAAfta,KAAK6R,OACTwI,OAAO9Y,KACLvB,KAAKooB,OAAOiO,sBAGhB,IAAmB,MAAfr2B,KAAK6R,MAAe,CAGtB,IAFAyI,eAEMta,KAAKooB,OAAOvW,QAAU7R,KAAKsc,KACZ,MAAftc,KAAK6R,OACTyI,YAAY/Y,KAAKvB,KAAK43B,wBACtB53B,KAAKuzB,OAAO,IAEVvzB,MAAKuzB,OAAO,MACdvzB,KAAKizB,uBAGHjzB,MAAKuzB,OAAO,MACdvzB,KAAKizB,kBAGT,OAAOztB,MAAK6U,OAAQC,cAQrBsd,qBAAsB;AACrB,GAAIpyB,MAAOxF,KAAKwF,OACZqU,MAAQ,KACRC,OAAS9Z,KAAKq2B,qBAclB,IAZIr2B,KAAK6R,QAAU7R,KAAKmc,IAAIsS,eACtBzuB,KAAKooB,OAAOmL,OAAOvzB,KAAKmc,IAAIoP,YAC9B1R,MAAQC,OACRA,OAAS9Z,KAAK2nB,OACd3nB,KAAKooB,QAIPtO,OAASA,OAAOtX,KAIdxC,KAAK6R,QAAU7R,KAAKmc,IAAIuH,YAC1B,MAAOle,MACL,kBACAqU,MAAOC,OACP9Z,KAAKooB,OAAOkO,iBAKX,IAAIt2B,KAAK6R,QAAU7R,KAAKmc,IAAIyE,KAAM,CACrC,GAAI3S,QAAQ,EACRkN,MAAQ,IAaZ,OAZInb,MAAKooB,OAAOmM,GAAG,oBACjBtmB,MAAQjO,KAAKy2B,qBAGXz2B,KAAK6R,QAAU7R,KAAKmc,IAAIoP,UAC1BpQ,MAAQnb,KAAK2nB,OACb3nB,KAAKooB,QACIna,SAAU,GAEnBjO,KAAKuzB,OAAOvzB,KAAKmc,IAAIoP,UAGhB/lB,KAAK,aAAcqU,MAAOC,OAAQqB,MAAOlN,OAKlD,MADAjO,MAAKuzB,QAAQvzB,KAAKmc,IAAIyE,KAAM5gB,KAAKmc,IAAIuH,cAC9Ble,KAAK,aAAcqU,MAAOC,OAAQ,KAAM,aAI7C+d,KAAK,SAASt5B,QAAQkB,OAAOJ,SAOnC,GAAIy4B,UAAW,8BAEfr4B,QAAOJ,SAIL43B,aAAc,WACZ,GAAIjzB,QAAShE,KAAKwF,KAAK,OACnBmL,QACJ,GAAG,CACD,GAAImB,MAAO9R,KAAK2nB,MACA,OAAZ7V,KAAK,GACPA,KAAOA,KAAK5M,UAAU,IAEtB4M,KAAOA,KAAK5M,UAAU,GACkB,OAApC4M,KAAK5M,UAAU4M,KAAKvS,OAAS,KAC/BuS,KAAOA,KAAK5M,UAAU,EAAG4M,KAAKvS,OAAS,KAG3CoR,MAAMpP,KAAKuQ,KAAKsiB;OACVp0B,KAAKizB,mBAAmBphB,QAAU7R,KAAKmc,IAAImM,UACnD,OAAOtkB,SAAO,EAAO2M,QAKvBqmB,iBAAkB,WAChB,GAAIhzB,QAAShE,KAAKwF,KAAK,OACnBmiB,KAAO3nB,KAAK2nB,MAChBA,MAAOA,KAAKziB,UAAU,EAAGyiB,KAAKpoB,OAAS,EACvC,IAAIoR,SACJgX,MAAOA,KAAKwM,MAAM2D,SAClB,KAAI,GAAI94B,GAAI,EAAGA,EAAI2oB,KAAKpoB,OAAQP,GAAK,EACnC2R,MAAMpP,KAAKomB,KAAK3oB,GAAGo1B,OAGrB,OADAp0B,MAAKizB,mBACEjvB,QAAO,EAAM2M,cAIlBonB,KAAK,SAASx5B,QAAQkB,OAAOJ,SAMnC,YAEAI,QAAOJ,SAELw2B,UAAW,WACT,GAAI7xB,QAAShE,KAAKwF,OACdiT,KAAOzY,KAAKg4B,gBAEhB,IAAmB,MAAfh4B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN,YAC9C,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN,YAC9C,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN,YAC9C,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN,YAC9C,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN,YAC9C,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN,YAC9C,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN,YAC9C,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN;AAC9C,GAAmB,MAAf71B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN,YAC9C,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAIqU,MAC1B,MAAOxsB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN,YAC/C,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAI2T,KAC1B,MAAO9rB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN,YAC/C,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAIiU,KAC1B,MAAOpsB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN,YAE/C,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAIgV,aAC1B,MAAOntB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN,YAC/C,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAImJ,aAC1B,MAAOthB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN,YAC/C,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAI6U,cAC1B,MAAOhtB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN,YAC/C,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAIqJ,cAC1B,MAAOxhB,QAAO,MAAO,MAAOyU,KAAMzY,KAAKooB,OAAOyN,YAChD,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAIuJ,cAC1B,MAAO1hB,QAAO,MAAO,MAAOyU,KAAMzY,KAAKooB,OAAOyN,YAChD,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAI+S,eAC1B,MAAOlrB,QAAO,MAAO,MAAOyU,KAAMzY,KAAKooB,OAAOyN,YAChD,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAIqT,mBAC1B,MAAOxrB,QAAO,MAAO,MAAOyU,KAAMzY,KAAKooB,OAAOyN,YAChD,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAIgT,WAC1B,MAAOnrB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN;AAC/C,GAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAIsT,eAC1B,MAAOzrB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN,YAC/C,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN,YAC9C,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7N,QAAO,MAAO,IAAKyU,KAAMzY,KAAKooB,OAAOyN,YAC9C,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAI6T,sBAC1B,MAAOhsB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN,YAC/C,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAI+T,sBAC1B,MAAOlsB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN,YAC/C,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAI4T,YAC1B,MAAO/rB,QAAO,MAAO,MAAOyU,KAAMzY,KAAKooB,OAAOyN,YAChD,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAIwE,aAC1B,MAAO3c,QAAO,MAAO,aAAcyU,KAAMzY,KAAKooB,OAAOyN,YAIvD,IAAI71B,KAAK6R,QAAU7R,KAAKmc,IAAIwT,WAC1B,MAAO3rB,QAAO,MAAO,KAAMyU,KAAMzY,KAAKooB,OAAOyN,YAI/C,IAAmB,MAAf71B,KAAK6R,MAAe,CACtB,GAAIomB,SAAU,IAKd,OAJ0B,MAAtBj4B,KAAKooB,OAAOvW,QACdomB,QAAUj4B,KAAK61B,aAEjB71B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,OAClBpkB,OAAO,QAASyU,KAAMwf,QAASj4B,KAAK61B,aAG7C,MAAOpd,OASRuf,eAAgB,WAEf,GAAmB,MAAfh4B,KAAK6R,MACP,MAAO7R,MAAKwF,KAAK,UAAUxF,KAAKooB,OAAOyN,YACzC,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7R,MAAKwF,KAAK,SAAS,IAAKxF,KAAKooB,OAAOyN;AAC7C,GAAmB,MAAf71B,KAAK6R,MACP,MAAO7R,MAAKwF,KAAK,SAAS,IAAKxF,KAAKooB,OAAOyN,YAC7C,IAAmB,MAAf71B,KAAK6R,MACP,MAAO7R,MAAKwF,KAAK,SAAS,IAAKxF,KAAKooB,OAAOyN,YAE7C,IAAmB,MAAf71B,KAAK6R,MAAe,CACtB,GAAI7N,QAAShE,KAAKwF,MAElB,OADAxF,MAAKooB,OAEHpoB,KAAK6R,QAAU7R,KAAKmc,IAAI6O,WACxBhrB,KAAK6R,QAAU7R,KAAKmc,IAAI4O,WAGxB/mB,OAASA,OAAO,SAAU,IAAMhE,KAAK2nB,QACrC3nB,KAAKooB,OACEpkB,QAEAA,OAAO,QAAS,IAAKhE,KAAK61B,aAIrC,GAAmB,MAAf71B,KAAK6R,MAAe,CACtB,GAAIrM,MAAOxF,KAAKwF,KAAK,eACjBiT,KAAOzY,KAAKooB,OAAOyN,WAIvB,OAHA71B,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzB3P,KAAOjT,KAAKiT,MAERzY,KAAK6R,QAAU7R,KAAKmc,IAAIiP,kBACnBprB,KAAKk4B,8BAA8Bzf,MAAM,GACvCzY,KAAK6R,QAAU7R,KAAKmc,IAAIoR,cAA+B,MAAfvtB,KAAK6R,MAC/C7R,KAAKm4B,oBAAoB1f,MACR,MAAfzY,KAAK6R,MAEP7R,KAAKwF,KAAK,QACfiT,KAAMzY,KAAKo4B,+BAGN3f,KAIX,GAAmB,MAAfzY,KAAK6R,MAEP,MAAO7R,MAAKooB,OAAOiQ,qBAAqB,IAG1C,IAAIr4B,KAAK6R,QAAU7R,KAAKmc,IAAI8I,OAAQ,CAClC,GAAIjhB,QAAShE,KAAKwF,KAAK,QAAS8yB,OAAS,KACrCC,QAAUv4B,KAAK8yB,SACdyF,WACHD,OAASt4B,KAAKwF,KAAK,WAEjBxF,KAAKooB,OAAOmL,OAAO,MACrBvzB,KAAKooB,OAGFpoB,KAAK8yB,YAAW9yB,KAAK8yB,WAAY;AAKtC,IAAI,GAJA0F,YAAax4B,KAAKy4B,uBAGlBC,SAAU,EACN15B,EAAI,EAAGA,EAAIw5B,WAAWj5B,OAAQP,IACpC,GAAsB,OAAlBw5B,WAAWx5B,GAAa,CAC1B05B,SAAU,CACV,OAYJ,MATKA,UACH14B,KAAKqzB,WACH,gDAAkDrzB,KAAKqD,MAAMC,OAAOC,YAGpEvD,KAAKuzB,OAAO,MACdvzB,KAAKooB,OAGFmQ,QAaIv0B,OAAOw0B,aAZdx4B,KAAK8yB,WAAY,EACb9yB,KAAKuzB,OAAO,KACP+E,OACLt0B,OAAOw0B,YACPx4B,KAAKooB,OAAOyN,YACZ,KAIK7xB,OAAOw0B,aAOpB,GAAIx4B,KAAK6R,QAAU7R,KAAKmc,IAAIsG,QAC1B,MAAOziB,MAAKwF,KAAK,SACfxF,KAAKooB,OAAOyN,YAGhB,QAAO71B,KAAK6R,OAEV,IAAK7R,MAAKmc,IAAIkT,MACZ,MAAOrvB,MAAKwF,KAAK,OACf,IAAKxF,KAAKooB,OAAOwN,eAAc,GAAO,GAAO,GAGjD,KAAK51B,MAAKmc,IAAI+R,MACZ,MAAOluB,MAAKwF,KAAK,OACf,IAAKxF,KAAKooB,OAAOwN,eAAc,GAAO,GAAO,GAGjD,KAAK51B,MAAKmc,IAAIoG,MACZ,MAAOviB,MAAKooB,OAAOuQ,eAErB,KAAK34B,MAAKmc,IAAI2H,QACZ,GAAI9f,QAAShE,KAAKwF,KAAK,QACnBxF,MAAKooB,OAAOmL,OAAO,MACrBvzB,KAAKooB,MAEP,IAAIhnB,MAAOpB,KAAKk3B,UAAUl3B,KAAK61B,UAAW,IAI1C,OAHI71B,MAAKuzB,OAAO,MACdvzB,KAAKooB,OAEApkB,OAAO5C,KAEhB,KAAKpB,MAAKmc,IAAI6H,QACZ,GAAIhgB,QAAShE,KAAKwF,KAAK,QACnBxF,MAAKooB,OAAOmL,OAAO,MACrBvzB,KAAKooB,MAEP,IAAIwQ,KAAM54B,KAAK61B;AAIf,MAHI71B,MAAKuzB,OAAO,MACdvzB,KAAKooB,OAEApkB,QAAQ40B,KAEjB,KAAK54B,MAAKmc,IAAI4G,UACZ,MAAO/iB,MAAKwF,KAAK,YACf,GAAO,EACPxF,KAAKooB,OAAOyN,YAGhB,KAAK71B,MAAKmc,IAAI8G,eACZ,MAAOjjB,MAAKwF,KAAK,YACf,GAAM,EACNxF,KAAKooB,OAAOyN,YAGhB,KAAK71B,MAAKmc,IAAI+G,UACZ,MAAOljB,MAAKwF,KAAK,YACf,GAAO,EACPxF,KAAKooB,OAAOyN,YAGhB,KAAK71B,MAAKmc,IAAIiH,eACZ,MAAOpjB,MAAKwF,KAAK,YACf,GAAM,EACNxF,KAAKooB,OAAOyN,YAGhB,KAAK71B,MAAKmc,IAAI0G,OACZ,GAAI7e,QAAShE,KAAKwF,KAAK,OACnBxF,MAAKooB,OAAOmL,OAAO,MACrBvzB,KAAKooB,MAEP,IAAI3P,MAAOzY,KAAK61B,WAIhB,OAHI71B,MAAKuzB,OAAO,MACdvzB,KAAKooB,OAEApkB,OAAOyU,KAEhB,KAAKzY,MAAKmc,IAAI0J,WACZ,MAAO7lB,MAAKwF,KAAK,QAAQ,MAAOxF,KAAKooB,OAAOyN,YAE9C,KAAK71B,MAAKmc,IAAI6J,cACZ,MAAOhmB,MAAKwF,KAAK,QAAQ,SAAUxF,KAAKooB,OAAOyN,YAEjD,KAAK71B,MAAKmc,IAAIiK,cACZ,MAAOpmB,MAAKwF,KAAK,QAAQ,SAAUxF,KAAKooB,OAAOyN,YAEjD,KAAK71B,MAAKmc,IAAImK,aACZ,MAAOtmB,MAAKwF,KAAK,QAAQ,QAASxF,KAAKooB,OAAOyN,YAEhD,KAAK71B,MAAKmc,IAAIqK,cACZ,MAAOxmB,MAAKwF,KAAK,QAAQ,SAAUxF,KAAKooB,OAAOyN,YAEjD,KAAK71B,MAAKmc,IAAIuK,YACZ,MAAO1mB,MAAKwF,KAAK,QAAQ,UAAWxF,KAAKooB,OAAOyN;AAElD,IAAK71B,MAAKmc,IAAIyK,aACZ,MAAO5mB,MAAKwF,KAAK,SACfxF,KAAKooB,OAAOyN,YAGhB,KAAK71B,MAAKmc,IAAI6B,OACZ,GAAIha,QAAShE,KAAKwF,KAAK,QACnB6M,OAAS,IAWb,OAV2B,MAAtBrS,KAAKooB,OAAOvW,QACW,MAAtB7R,KAAKooB,OAAOvW,OACdQ,OAASrS,KAAK61B,YACV71B,KAAKuzB,OAAO,MACdvzB,KAAKooB,QAGPpoB,KAAKooB,QAGFpkB,OAAOqO,OAEhB,KAAKrS,MAAKmc,IAAI2F,QACZ,MAAO9hB,MAAKwF,KAAK,SACfxF,KAAKooB,OAAOyN,YAIhB,KAAK71B,MAAKmc,IAAI0R,QACZ,GAAI7pB,QAAShE,KAAKwF,KAAK,SAAUmH,MAAQ,KAAM+E,IAAM,IAUrD,OATI1R,MAAKooB,OAAOmM,GAAG,UAEjB5nB,MAAQ3M,KAAK61B,YACT71B,KAAK6R,QAAU7R,KAAKmc,IAAI8S,iBAE1Bvd,IAAM/E,MACNA,MAAQ3M,KAAKooB,OAAOyN,cAGjB7xB,OAAO2I,MAAO+E,IAGvB,KAAK1R,MAAKmc,IAAIyR,aACZ,GAAI5pB,QAAShE,KAAKwF,KAAK,aACnBiT,KAAOzY,KAAKooB,OAAOyN,WACvB,OAAO7xB,QAAOyU,KAEhB,KAAKzY,MAAKmc,IAAIgC,WACZ,MAAOne,MAAK42B,eAAc,EAE5B,KAAK52B,MAAKmc,IAAIiI,SACZ,GAAIyU,SAAU74B,KAAK6R,MAAO7R,KAAKqD,MAAM0kB,WACrC,IAAI/nB,KAAKooB,OAAOvW,QAAU7R,KAAKmc,IAAIgC,WAEjC,MAAOne,MAAK42B,eAAc,GAAO,EAAG,EAAG,GAGvC52B,MAAKqD,MAAM+Y,OAAO7a,KAAKs3B,QACvB74B,KAAKooB,OAOX,GAAI3P,KACJ,IAAIzY,KAAKu0B,GAAG,YAAa,CACvB,GAAIvwB,QAAShE,KAAKwF,MAClBiT,MAAOzY,KAAK41B,eAAc,GAAO,GAAO;AAIxC,GAAIkD,SACY,aAAdrgB,KAAKvU,MACW,iBAAduU,KAAKvU,MACgB,aAArBuU,KAAKtT,OAAOjB,IAKhB,QAAOlE,KAAK6R,OACV,IAAK,IACCinB,SAAS94B,KAAK6zB,MAAM,WACxB,IAAI1vB,MAUJ,OAPIA,OAFqB,KAArBnE,KAAKooB,OAAOvW,MACV7R,KAAKooB,OAAOvW,QAAU7R,KAAKmc,IAAIoG,MACzBviB,KAAKooB,OAAOuQ,gBAEZ34B,KAAK41B,eAAc,GAAO,GAAO,GAGnC51B,KAAK61B,YAER7xB,OAAO,SAAUyU,KAAMtU,MAAO,IAGvC,KAAKnE,MAAKmc,IAAImT,aAEZ,MADIwJ,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa,KAEzD,KAAK71B,MAAKmc,IAAIgS,cAEZ,MADI2K,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa,KAEzD,KAAK71B,MAAKmc,IAAImU,YAEZ,MADIwI,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa,KAEzD,KAAK71B,MAAKmc,IAAIoU,YAEZ,MADIuI,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa,MAEzD,KAAK71B,MAAKmc,IAAIoS,YAEZ,MADIuK,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa,KAEzD,KAAK71B,MAAKmc,IAAIuU,eAEZ,MADIoI,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa;AAEzD,IAAK71B,MAAKmc,IAAI0U,YAEZ,MADIiI,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa,KAEzD,KAAK71B,MAAKmc,IAAI4U,YAEZ,MADI+H,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa,KAEzD,KAAK71B,MAAKmc,IAAI+U,WAEZ,MADI4H,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa,KAEzD,KAAK71B,MAAKmc,IAAIkV,YAEZ,MADIyH,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa,KAEzD,KAAK71B,MAAKmc,IAAI0T,WAEZ,MADIiJ,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAAUyU,KAAMzY,KAAKooB,OAAOyN,YAAa,MAEzD,KAAK71B,MAAKmc,IAAIgU,WAEZ,MADI2I,UAAS94B,KAAK6zB,MAAM,YACjB7vB,OAAO,SAASyU,KAAMzY,KAAKooB,OAAOyN,YAAa,MAExD,KAAK71B,MAAKmc,IAAIkT,MAGZ,MAFIyJ,UAAS94B,KAAK6zB,MAAM,YACxB7zB,KAAKooB,OACEpkB,OAAO,OAAQ,IAAKyU,KAC7B,KAAKzY,MAAKmc,IAAI+R,MAGZ,MAFI4K,UAAS94B,KAAK6zB,MAAM,YACxB7zB,KAAKooB,OACEpkB,OAAO,OAAQ,IAAKyU,WAE1B,IAAIzY,KAAKu0B,GAAG,UAGjB,IAFA9b,KAAOzY,KAAK+4B,cAEN/4B,KAAK6R,QAAU7R,KAAKsc,KACxB,GAAItc,KAAK6R,QAAU7R,KAAKmc,IAAIiP,kBAC1B3S,KAAOzY,KAAKk4B,8BAA8Bzf,MAAM,OAC3C,IAAIzY,KAAK6R,QAAU7R,KAAKmc,IAAIoR,cAA+B,MAAfvtB,KAAK6R,MACtD4G,KAAOzY,KAAKm4B,oBAAoB1f,UAC3B;AAAA,GAAmB,MAAfzY,KAAK6R,MAId,MAAO4G,KAFPA,MAAOzY,KAAKwF,KAAK,QAAQiT,KAAMzY,KAAKo4B,mCAMxCp4B,MAAK6zB,MAAM,QACX7zB,KAAKooB,MAIP,OAAO3P,OASRkgB,cAAe,WACd,GAAI30B,QAAShE,KAAKwF,KAAK,MACvB,IAAIxF,KAAK6R,QAAU7R,KAAKmc,IAAI6F,QAAS,CACnC,GAAIvd,MAAOzE,KAAKwF,KAAK,SAEjB2wB,YAAc,KAAMC,eAAiB,KAAM9oB,KAAO,KAAMlM,OAa5D,OAZ0B,MAAtBpB,KAAKooB,OAAOvW,QACdzQ,KAAOpB,KAAKo4B,+BAEVp4B,KAAK6R,OAAS7R,KAAKmc,IAAIiG,YACzB+T,YAAcn2B,KAAKooB,OAAOiO,uBAExBr2B,KAAK6R,OAAS7R,KAAKmc,IAAIkG,eACzB+T,eAAiBp2B,KAAKooB,OAAOkO,kBAE3Bt2B,KAAKuzB,OAAO,OACdjmB,KAAOtN,KAAKooB,OAAOmO,mBAEdvyB,OACLS,KACE,KACC0xB,YACAC,eACA9oB,MACC,EAAG,EAAG,IACPlM,MAIL,GAAIoB,MAAOxC,KAAKg5B,4BACZ53B,OAIJ,OAHmB,MAAfpB,KAAK6R,QACPzQ,KAAOpB,KAAKo4B,+BAEPp0B,OAAOxB,KAAMpB,OASvB43B,0BAA2B,WAC1B,GACEh5B,KAAK6R,QAAU7R,KAAKmc,IAAIkS,gBACxBruB,KAAK6R,QAAU7R,KAAKmc,IAAIoP,UACxBvrB,KAAK6R,QAAU7R,KAAKmc,IAAImH,YACxB,CACA,GAAItf,QAAShE,KAAKq2B,qBAIlB,OAHIr2B,MAAK6R,QAAU7R,KAAKmc,IAAIsS,iBAC1BzqB,OAAShE,KAAKi5B,mBAAmBj1B;AAE5BA,OACF,MAAIhE,MAAKu0B,GAAG,YACVv0B,KAAK41B,eAAc,GAAM,GAAO,OAEvC51B,MAAKuzB,QAAQvzB,KAAKmc,IAAIoP,SAAU,cAQnCkN,qBAAsB,WACrB,MAAOz4B,MAAKk3B,UACVl3B,KAAKk5B,6BAA8B,MAStCA,6BAA8B,WAC7B,GAAmB,MAAfl5B,KAAK6R,OAAgC,MAAf7R,KAAK6R,MAAe,MAAO,KACrD,IAAI7N,QAAShE,KAAKg4B,gBAQlB,OAPIh4B,MAAK6R,QAAU7R,KAAKmc,IAAI8S,iBAC1BjrB,QACE,MACAA,OACAhE,KAAKooB,OAAO4P,mBAGTh0B,cAILm1B,KAAK,SAAS56B,QAAQkB,OAAOJ,SAOnCI,OAAOJ,SAIL+5B,aAAc,WACZ,MAAkB,KAAdp5B,KAAK6R,QACP7R,KAAKooB,QACE,IAOViR,YAAa,WACZ,MAAIr5B,MAAK6R,QAAU7R,KAAKmc,IAAIwU,aAC1B3wB,KAAKooB,QACE,IAUVwO,cAAe,SAAS0C,QAASrD,MAChC,GAAIjyB,QAAShE,KAAK03B,0BAChB4B,QAAU,EAAKrD,KAAO,EAAI,EAC1BA,MAAoB,IAAZA,KAAK,GAmBf,OAjBIA,OAAmB,GAAXA,KAAK,IAEfjyB,OAAOoK,WAAW6nB,MACdj2B,KAAKuzB,OAAO,MACdvzB,KAAKizB,qBAGHjzB,KAAKuzB,OAAO,OACdvvB,OAAOsJ,KAAOtN,KAAKu5B,iBAAgB,GAC/Bv1B,OAAOmS,KAAOnS,OAAOsJ,KAAK6I,MAC5BnS,OAAOmS,IAAIf,IAAMpR,OAAOsJ,KAAK6I,IAAIf,OAGhCkkB,SAAWrD,MACdjyB,OAAOoK,WAAW6nB,OAGfjyB;AAQR0zB,0BAA2B,SAASrzB,KAAM4K,UACzC,GAAIuqB,UAAW,UACF,KAATn1B,KACFm1B,SAAW,UACO,IAATn1B,OACTm1B,SAAW,SAEb,IAAIx1B,QAAShE,KAAKwF,KAAKg0B,SAEnBx5B,MAAKuzB,OAAOvzB,KAAKmc,IAAIgC,aACvBne,KAAKooB,MAEP,IAAIrR,OAAQ/W,KAAKo5B,eACb52B,MAAO,EAAO+gB,OAAUkW,WAAa,KAAMzqB,UAAW,CAC7C,KAAT3K,MACErE,KAAKuzB,OAAOvzB,KAAKmc,IAAIoP,YACvB/oB,KAAOxC,KAAK2nB,OACZ3nB,KAAKooB,QAGLpoB,KAAKuzB,OAAO,MAAMvzB,KAAKooB,MAC3B,IAAIsR,QAAS15B,KAAK25B,qBAclB,OAbI35B,MAAKuzB,OAAO,MAAMvzB,KAAKooB,OACd,IAAT/jB,MAAcrE,KAAK6R,QAAU7R,KAAKmc,IAAIqH,QACpCxjB,KAAKooB,OAAOmL,OAAO,MAAMvzB,KAAKooB,OAClC7E,IAAMvjB,KAAKk3B,UAAUl3B,KAAK45B,iBAAkB,KACxC55B,KAAKuzB,OAAO,MAAMvzB,KAAKooB,QAEV,MAAfpoB,KAAK6R,QACmB,MAAtB7R,KAAKooB,OAAOvW,QACd7C,UAAW,EACXhP,KAAKooB,QAEPqR,WAAaz5B,KAAK65B,aAEP,IAATx1B,KAEKL,OAAO01B,OAAQ3iB,MAAOwM,IAAKkW,WAAYzqB,SAAUC,UAEnDjL,OAAOxB,KAAMk3B,OAAQ3iB,MAAO0iB,WAAYzqB,WAOhD4qB,iBAAkB,WACjB,GAAI51B,QAAShE,KAAKwF,KAAK,YACnBuR,OAAQ,CACO,OAAf/W,KAAK6R,QACPkF,OAAQ,EACR/W,KAAKooB,QAEPpoB,KAAKuzB,OAAOvzB,KAAKmc,IAAIyP,WACrB,IAAIppB,MAAOxC,KAAK2nB,OAAOziB,UAAU,EAEjC,OADAlF,MAAKooB,OACEpkB,OAAOxB,KAAMuU,OAAO;EAQ5B4iB,oBAAqB,WACpB,GAAI31B,UACJ,IAAkB,KAAdhE,KAAK6R,MACP,KAAM7R,KAAK6R,OAAS7R,KAAKsc,KAAK,CAE5B,GADAtY,OAAOzC,KAAKvB,KAAK85B,kBACC,KAAd95B,KAAK6R,MAEF,CAAA,GAAkB,KAAd7R,KAAK6R,MACd,KAEA7R,MAAK6zB,OAAO,IAAK,KACjB,OALA7zB,KAAKooB,OASX,MAAOpkB,SAQR81B,eAAgB,WACf,GAAIt0B,MAAOxF,KAAKwF,KAAK,aACnBhD,KAAO,KACPmK,MAAQ,KACRtI,KAAO,KACP2K,UAAW,CACM,OAAfhP,KAAK6R,QACP7R,KAAKooB,OACLpZ,UAAW,GAEb3K,KAAOrE,KAAK65B,YACR7qB,WAAa3K,MACfrE,KAAKqzB,WAAW,8DAElB,IAAItc,OAAQ/W,KAAKo5B,eACbpiB,WAAahX,KAAKq5B,aAQtB,OAPIr5B,MAAKuzB,OAAOvzB,KAAKmc,IAAIyP,cACvBppB,KAAOxC,KAAK2nB,OAAOziB,UAAU,GAC7BlF,KAAKooB,QAEW,KAAdpoB,KAAK6R,QACPlF,MAAQ3M,KAAKooB,OAAOyN,aAEfrwB,KAAKhD,KAAM6B,KAAMsI,MAAOoK,MAAOC,WAAYhI,WAQnDopB,4BAA6B,WAC5B,GAAIp0B,WACA+1B,aAAc,CAElB,IADA/5B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,OACN,MAAfpoB,KAAK6R,MACP,KAAM7R,KAAK6R,OAAS7R,KAAKsc,KAAK,CAC5B,GAAI0d,UAAWh6B,KAAKi6B,oBASpB,IARID,WACFh2B,OAAOzC,KAAKy4B,UACU,aAAlBA,SAAS91B,KACX61B,aAAc,EACLA,aACT/5B,KAAKqzB,WAAW;AAGD,MAAfrzB,KAAK6R,MAEF,KADL7R,MAAKooB,OAKX,MADApoB,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OAClBpkB,QAORi2B,mBAAoB,WACnB,MAAIj6B,MAAK6R,QAAU7R,KAAKmc,IAAIwU,WACnB3wB,KAAKwF,KAAK,YAAYxF,KAAKooB,OAAOyN,aAEpC71B,KAAK61B,aAQbgE,UAAW,WACV,GAAI71B,QAAShE,KAAKwF,KAAK,aACvB,QAAOxF,KAAK6R,OACV,IAAK7R,MAAKmc,IAAI+I,QAEZ,MADAllB,MAAKooB,OACEpkB,QAAQ,GAAI,UAAU,EAC/B,KAAKhE,MAAKmc,IAAImH,YACd,IAAKtjB,MAAKmc,IAAIkS,eACd,IAAKruB,MAAKmc,IAAIoP,SACZ,MAAOvrB,MAAKq2B,qBACd,KAAKr2B,MAAKmc,IAAIiJ,WAEZ,MADAplB,MAAKooB,OACEpkB,QAAQ,GAAI,aAAa,EAClC,SACE,MAAO,cAKTk2B,KAAK,SAAS37B,QAAQkB,OAAOJ,SAOnCI,OAAOJ,SAQL86B,QAAS,WACP,GAAIn2B,QAAShE,KAAKwF,KAAK,MACrB8H,KAAO,KACP8G,UAAY,KACZ1I,WAAY,EACZlH,KAAO,IAGT,IAFAA,KAAOxE,KAAKo6B,eAEO,MAAfp6B,KAAK6R,MAAe,CACtBnG,WAAY,EACZ1L,KAAKooB,OACL9a,KAAOtN,KAAKwF,KAAK,QAEjB,KADA,GAAImG,UACE3L,KAAK6R,QAAU7R,KAAKsc,KAAOtc,KAAK6R,QAAU7R,KAAKmc,IAAIkD,SAAS,CAChE,GAAIrf,KAAK6R,QAAU7R,KAAKmc,IAAIgD,SAAU,CACpC/K,UAAYpU,KAAKooB,OAAOiS,mBACxB,OACK,GAAIr6B,KAAK6R,QAAU7R,KAAKmc,IAAIoD,OAAQ,CACzCnL,UAAYpU,KAAKooB,OAAOkS;AACxB,MAEF3uB,MAAMpK,KAAKvB,KAAKu6B,wBAElBjtB,KAAOA,KAAK,KAAM3B,OAClB3L,KAAKuzB,OAAOvzB,KAAKmc,IAAIkD,UAAYrf,KAAKooB,OACtCpoB,KAAKg0B,2BAEL1mB,MAAOtN,KAAKw6B,iBAIZx6B,KAAKs0B,iBACDt0B,KAAK6R,QAAU7R,KAAKmc,IAAIgD,SAC1B/K,UAAYpU,KAAKooB,OAAO+R,UACfn6B,KAAK6R,QAAU7R,KAAKmc,IAAIoD,SACjCnL,UAAYpU,KAAKooB,OAAOoS,iBAG5B,OAAOx2B,QAAOQ,KAAM8I,KAAM8G,UAAW1I,YAKvC0uB,aAAc,WACZp6B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,MACzB,IAAIpkB,QAAShE,KAAK61B,WAElB,OADA71B,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OAClBpkB,QAKTq2B,kBAAmB,WACjB,GAAIr2B,QAAShE,KAAKwF,KAAK,MACrB4O,UAAY,KACZ5P,KAAO,KACP8I,KAAO,KACP3B,QAIF,KAHAnH,KAAOxE,KAAKo6B,eACRp6B,KAAKuzB,OAAO,MAAMvzB,KAAKooB,OAC3B9a,KAAOtN,KAAKwF,KAAK,SACXxF,KAAK6R,OAAS7R,KAAKsc,KAAOtc,KAAK6R,QAAU7R,KAAKmc,IAAIkD,SAAS,CAC/D,GAAIrf,KAAK6R,QAAU7R,KAAKmc,IAAIgD,SAAU,CACpC/K,UAAYpU,KAAKooB,OAAOiS,mBACxB,OACK,GAAIr6B,KAAK6R,QAAU7R,KAAKmc,IAAIoD,OAAQ,CACzCnL,UAAYpU,KAAKooB,OAAOkS,iBACxB,OAEF3uB,MAAMpK,KAAKvB,KAAKu6B,wBAGlB,MADAjtB,MAAOA,KAAK,KAAM3B,OACX3H,OAAOQ,KAAM8I,KAAM8G,WAAW,IAKvCkmB,gBAAiB;AACXt6B,KAAKuzB,OAAO,MAAMvzB,KAAKooB,MAE3B,KADA,GAAI9a,MAAOtN,KAAKwF,KAAK,SAAUmG,SACzB3L,KAAK6R,OAAS7R,KAAKsc,KAAOtc,KAAK6R,QAAU7R,KAAKmc,IAAIkD,SACtD1T,MAAMpK,KAAKvB,KAAKu6B,uBAElB,OAAOjtB,MAAK,KAAM3B,cAIhB8uB,KAAK,SAASl8B,QAAQkB,OAAOJ,SAMnC,YACAI,QAAOJ,SASLq7B,WAAY,WACV,GAAI12B,QAAShE,KAAKwF,KAAK,SACrBhB,KAAO,KACP8I,KAAO,KACP5B,WAAY,CAWd,OATI1L,MAAKuzB,OAAO,MAAMvzB,KAAKooB,OAC3B5jB,KAAOxE,KAAK61B,YACR71B,KAAKuzB,OAAO,MAAMvzB,KAAKooB,OACR,MAAfpoB,KAAK6R,OACPnG,WAAY,EACZ4B,KAAOtN,KAAK26B,gBAAgB36B,KAAKmc,IAAIwD,aAErCrS,KAAOtN,KAAKw6B,iBAEPx2B,OAAOQ,KAAM8I,KAAM5B,YAU3BkvB,QAAS,WACR,GAAI52B,QAAShE,KAAKwF,KAAK,MACrBhB,KAAO,KACP8I,KAAO,IAST,OAPAA,MAAOtN,KAAKw6B,iBACRx6B,KAAKs0B,iBAAiBf,OAAOvzB,KAAKmc,IAAIsD,WACpCzf,KAAKooB,OAAOmL,OAAO,MAAMvzB,KAAKooB,OAClC5jB,KAAQxE,KAAK61B,YACT71B,KAAKuzB,OAAO,MAAMvzB,KAAKooB,OACvBpoB,KAAKuzB,OAAO,MAAMvzB,KAAKooB,QAEtBpkB,OAAOQ,KAAM8I,OAYrButB,SAAU,WACT,GAAI72B,QAAShE,KAAKwF,KAAK,OACrBkN,QACAlO,QACAmO,aACArF,KAAO,KACP5B,WAAY,CA0Bd,OAzBI1L,MAAKuzB,OAAO,MAAMvzB,KAAKooB,OACR,MAAfpoB,KAAK6R,OACPa,KAAO1S,KAAKk3B,UAAUl3B,KAAK61B,UAAW;AAClC71B,KAAKuzB,OAAO,MAAMvzB,KAAKooB,QAE3BpoB,KAAKooB,OAEY,MAAfpoB,KAAK6R,OACPrN,KAAOxE,KAAKk3B,UAAUl3B,KAAK61B,UAAW,KAClC71B,KAAKuzB,OAAO,MAAMvzB,KAAKooB,QAE3BpoB,KAAKooB,OAEY,MAAfpoB,KAAK6R,OACPc,UAAY3S,KAAKk3B,UAAUl3B,KAAK61B,UAAW,KACvC71B,KAAKuzB,OAAO,MAAMvzB,KAAKooB,QAE3BpoB,KAAKooB,OAEY,MAAfpoB,KAAK6R,OACPnG,WAAY,EACZ4B,KAAOtN,KAAK26B,gBAAgB36B,KAAKmc,IAAI8D,WAErC3S,KAAOtN,KAAKw6B,iBAEPx2B,OAAO0O,KAAMlO,KAAMmO,UAAWrF,KAAM5B,YAU5CovB,aAAc,WACb,GAAI92B,QAAShE,KAAKwF,KAAK,WACrB0M,OAAS,KACTR,IAAM,KACN/E,MAAQ,KACRW,KAAO,KACP5B,WAAY,CAoBd,OAnBI1L,MAAKuzB,OAAO,MAAMvzB,KAAKooB,OAC3BlW,OAASlS,KAAK61B,YACV71B,KAAKs0B,iBAAiBf,OAAOvzB,KAAKmc,IAAIyE,QACxC5gB,KAAKooB,OACLzb,MAAQ3M,KAAK+6B,wBACT/6B,KAAK6R,QAAU7R,KAAKmc,IAAI8S,iBAC1Bvd,IAAM/E,MACNA,MAAQ3M,KAAKooB,OAAO2S,0BAIpB/6B,KAAKuzB,OAAO,MAAMvzB,KAAKooB,OAER,MAAfpoB,KAAK6R,OACPnG,WAAY,EACZ4B,KAAOtN,KAAK26B,gBAAgB36B,KAAKmc,IAAIkE,eAErC/S,KAAOtN,KAAKw6B,iBAEPx2B,OAAOkO,OAAQR,IAAK/E,MAAOW,KAAM5B,YAYzCqvB,sBAAuB,WACpB,GAAI/6B,KAAK6R,QAAU7R,KAAKmc,IAAI8I,OAAQ,CAClC,GAAIjhB,QAAShE,KAAKwF,KAAK;AACnBxF,KAAKooB,OAAOmL,OAAO,MAAMvzB,KAAKooB,MAClC,IAAIoQ,YAAax4B,KAAKy4B,sBAEtB,OADIz4B,MAAKuzB,OAAO,MAAMvzB,KAAKooB,OACpBpkB,OAAOw0B,YACT,MAAmB,MAAfx4B,KAAK6R,OAAiB7R,KAAK6R,QAAU7R,KAAKmc,IAAI+I,QAChDllB,KAAK01B,aAEL11B,KAAK41B,eAAc,GAAO,GAAO,UAK1CoF,KAAK,SAASz8B,QAAQkB,OAAOJ,SAOnCI,OAAOJ,SAML6zB,WAAY,WACV,MAAIlzB,MAAK6R,OAAS7R,KAAKmc,IAAImH,YAClBtjB,KAAKi7B,iBAELj7B,KAAKk7B,4BAKZC,KAAK,SAAS58B,QAAQkB,OAAOJ,SAMnC,YAEAI,QAAOJ,SAYL47B,eAAgB,WACd,GAAIj3B,QAAShE,KAAKwF,KAAK,YAEvB,IADAxF,KAAKuzB,OAAOvzB,KAAKmc,IAAImH,cAAgBtjB,KAAKooB,OACxB,KAAdpoB,KAAK6R,MAAc,CACrB7R,KAAK6yB,kBAAoB,GACzB,IAAIvlB,MAAQtN,KAAKizB,mBAAmBmI,qBAEpC,OADAp7B,MAAKuzB,OAAO,MAAQvzB,KAAKizB,mBAClBjvB,QAAQ,IAAKsJ,MAAM,GAE1B,GAAI9K,MAAOxC,KAAKq2B,qBAChB,IAAkB,KAAdr2B,KAAK6R,MAAc,CACrB7R,KAAK6yB,iBAAmBrwB,IACxB,IAAI8K,MAAOtN,KAAKizB,mBAAmBmI,qBAEnC,OADAp7B,MAAKuzB,OAAOvzB,KAAKsc,KACVtY,OAAOxB,KAAKA,KAAM8K,MAAM,GAC1B,GAAkB,KAAdtN,KAAK6R,MAAc,CAC5B7R,KAAK6yB,iBAAmBrwB,IACxB,IAAI8K,MAAQtN,KAAKizB,mBAAmBmI;AAEpC,MADAp7B,MAAKuzB,OAAO,MAAQvzB,KAAKizB,mBAClBjvB,OAAOxB,KAAKA,KAAM8K,MAAM,GAC1B,GAAmB,MAAftN,KAAK6R,MAId,MAFArP,MAAKoR,WAAa5T,KAAK8xB,IAAIziB,WAAWwE,cACtCrR,KAAKA,KAAOA,KAAKA,KAAK0C,UAAU,GACzBlF,KAAKwF,KAAK,QACfhD,KAAMxC,KAAKo4B,8BAGbp4B,MAAK6zB,OAAO,IAAK,MAEjB7zB,KAAK6yB,iBAAmBrwB,IACxB,IAAI8K,MAAOtN,KAAKo7B,qBAEhB,OADAp7B,MAAKuzB,OAAOvzB,KAAKsc,KACVtY,OAAOxB,KAAM8K,MAAM,IAY/B+oB,oBAAqB,WACpB,GAAIryB,QAAShE,KAAKwF,KAAK,cAAe61B,UAAW,CAKjD,OAJIr7B,MAAK6R,QAAU7R,KAAKmc,IAAImH,cAC1BtjB,KAAKooB,OAAOmL,OAAOvzB,KAAKmc,IAAIkS,iBAAmBruB,KAAKooB,OACpDiT,UAAW,GAENr3B,OACLhE,KAAKk3B,UAAUl3B,KAAKmc,IAAIoP,SAAUvrB,KAAKmc,IAAIkS,gBAAgB,GAC3DgN,WAeHC,mBAAoB,WACnB,GAAIt3B,QAAShE,KAAKwF,KAAK,YACrBnB,KAAO,KACPsH,SACAnJ,KAAO,IAaT,OAXAxC,MAAKuzB,OAAOvzB,KAAKmc,IAAIqH,QAAUxjB,KAAKooB,OACpC/jB,KAAOrE,KAAKu7B,gBACZ5vB,MAAMpK,KAAKvB,KAAKw7B,sBAAqB,IAClB,MAAfx7B,KAAK6R,MACPlG,MAAQA,MAAMlL,OAAOT,KAAKooB,OAAOqT,uBAAsB,IAC/B,MAAfz7B,KAAK6R,QACdrP,KAAOmJ,MAAM,GAAGnJ,KAChBmJ,MAAQ3L,KAAKooB,OAAOqT,sBAA+B,OAATp3B,MAC1CrE,KAAKuzB,OAAO,MAAQvzB,KAAKooB;AAE3BpoB,KAAKuzB,OAAO,MAAQvzB,KAAKizB,mBAClBjvB,OAAOxB,KAAM6B,KAAMsH,QAU3B6vB,qBAAsB,SAASE,OAC9B,GAAI13B,QAAShE,KAAKwF,KAAK,WAAYnB,KAAO,IACtCq3B,SAAOr3B,KAAOrE,KAAKu7B,gBACvB,IAAI/4B,MAAOxC,KAAKq2B,sBACZlb,MAAQnb,KAAK27B,gBACjB,OAAO33B,QAAOxB,KAAKA,KAAM2Y,MAAO9W,OAUjCo3B,sBAAuB,SAASC,OAE/B,IADA,GAAI13B,SAAUhE,KAAKw7B,qBAAqBE,QACnB,MAAf17B,KAAK6R,OACT7N,OAAOzC,KAAKvB,KAAKooB,OAAOoT,qBAAqBE,OAE/C,OAAO13B,SASR23B,eAAgB,WACf,GAAI33B,QAAS,IAOb,OANIhE,MAAK6R,QAAU7R,KAAKmc,IAAIyE,MACtB5gB,KAAKooB,OAAOmL,OAAOvzB,KAAKmc,IAAIoP,YAC9BvnB,OAAShE,KAAK2nB,OACd3nB,KAAKooB,QAGFpkB,QAURu3B,cAAe,WACd,MAAIv7B,MAAK6R,QAAU7R,KAAKmc,IAAIgC,YAC1Bne,KAAKooB,OACEpoB,KAAK8xB,IAAI8J,QAAQvgB,eACfrb,KAAK6R,QAAU7R,KAAKmc,IAAIkC,SACjCre,KAAKooB,OACEpoB,KAAK8xB,IAAI8J,QAAQxgB,YAEnB,YAILygB,KAAK,SAASt9B,QAAQkB,OAAOJ,SAOnC,GAAIy8B,cACFC,MAAO,KACPC,MAAO,KACPC,MAAO,KACPC,MAAOhjB,OAAOijB,aAAa,IAC3BC,MAAOljB,OAAOijB,aAAa,IAC3BE,MAAOnjB,OAAOijB,aAAa,IAC3BG,OAAQ,KACRC,MAAO,IACPC,MAAO,IACPC,MAAQ;CAGVh9B,QAAOJ,SAILq9B,sBAAuB,SAAS/U,MAC9B,MAAOA,MAAKgV,QACV,oBACA,SAASC,KACP,MAAOd,aAAYc,QAczB7D,YAAa,WACX,GAAI/4B,KAAKu0B,GAAG,iBACV,MAAOv0B,MAAK68B,oBAEZ,QAAO78B,KAAK6R,OAGV,IAAK7R,MAAKmc,IAAI+P,2BACZ,GAAIvf,OAAQ3M,KAAKwF,KAAK,UAClBmiB,KAAO3nB,KAAK2nB,OACZxO,cAA4B,MAAZwO,KAAK,EAIzB,OAHAA,MAAOA,KAAKziB,UAAU,EAAGyiB,KAAKpoB,OAAS,GACvCS,KAAKooB,OACLzb,MAAQA,MAAMwM,cAAenZ,KAAK08B,sBAAsB/U,OACpD3nB,KAAK6R,QAAU7R,KAAKmc,IAAIsS,eAEnBzuB,KAAKi5B,mBAAmBtsB,OAGxBA,KAEX,KAAK3M,MAAKmc,IAAI4Q,gBACZ,GAAgC,cAA5B/sB,KAAKqD,MAAMslB,aAA8B,CAC3C,GAAInjB,MAAOxF,KAAKwF,KAAK,UACjBmH,MAAQ3M,KAAKooB,OAAOT,OAEpBmV,OAASnwB,MAAMA,MAAMpN,OAAO,EAgBhC,OAfe,OAAXu9B,OAGAnwB,MAF4B,OAA1BA,MAAMA,MAAMpN,OAAO,GAEboN,MAAMzH,UAAU,EAAGyH,MAAMpN,OAAS,GAGlCoN,MAAMzH,UAAU,EAAGyH,MAAMpN,OAAS,GAExB,OAAXu9B,SAETnwB,MAAQA,MAAMzH,UAAU,EAAGyH,MAAMpN,OAAS,IAE5CS,KAAKuzB,OAAOvzB,KAAKmc,IAAI0P,4BAA8B7rB,KAAKooB,OACxD5iB,KAAOA,KAAKmH,MAAO3M,KAAKqD,MAAMypB,eAC9B9sB,KAAKuzB,OAAOvzB,KAAKmc,IAAIgR,gBAAkBntB,KAAKooB;AACrC5iB,KAEP,MAAOxF,MAAKooB,OAAOiQ,qBACjBr4B,KAAKmc,IAAIgR,cAIf,KAAK,IACH,MAAOntB,MAAKooB,OAAOiQ,qBAAqB,IAE1C,KAAK,KACL,IAAK,KACH,GAAI7yB,MAAOxF,KAAKwF,KAAK,QACjBf,KAAOzE,KAAKooB,OAAOiQ,qBAAqB,IAC5C,OAAO7yB,MAAK,SAAUf,KAGxB,KAAKzE,MAAKmc,IAAI6O,UACd,IAAKhrB,MAAKmc,IAAI4O,UACZ,GAAI/mB,QAAShE,KAAKwF,KAAK,UACnBmH,MAAQ3M,KAAK2nB,MAGjB,OAFA3nB,MAAKooB,OACLpkB,OAASA,OAAO2I,MAIlB,KAAK3M,MAAKmc,IAAI+I,QACd,IAAK,IACH,MAAOllB,MAAK01B,YACd,SACE,GAAIlC,KAAMxzB,KAAK6zB,MAAM,SAGrB,OADA7zB,MAAKooB,OACEoL,MAOd2E,oBAAqB,SAAS1f,MAC7B,GAAIzU,QACAwB,KAAOxF,KAAKwF,KAAK,eACrB,IAAmB,MAAfxF,KAAK6R,MAAe,CACtB,GAAI1M,QAASnF,KAAKooB,OAAOyN,WACrB71B,MAAKuzB,OAAO,MAAMvzB,KAAKooB,OAC3BpkB,OAASwB,KAAKiT,KAAMtT,YACf,IAAInF,KAAK6R,QAAU7R,KAAKmc,IAAIkR,2BAA4B,CAC7D,GAAIloB,QAASnF,KAAK+8B,2BAClB/4B,QAASwB,KAAKiT,KAAMtT,QAEtB,MAAOnB,SAiBR+4B,0BAA2B,WAC1B,GAAI/4B,QAAShE,KAAKwF,MAIlB,IAAIxF,KAAK6R,QAAU7R,KAAKmc,IAAI0P,0BAA2B,CACrD,GAAIlE,MAAO3nB,KAAK2nB,MAChB3nB,MAAKooB,OACLpkB,OAASA,OACP,UAAU,EAAOhE,KAAK08B,sBAAsB/U;KAM3C,IAAI3nB,KAAK6R,QAAU7R,KAAKmc,IAAIkR,2BAA4B,CAC3D,GAAI7qB,MAAO,IACX,IAAIxC,KAAKooB,OAAOvW,QAAU7R,KAAKmc,IAAIsP,iBAAkB,CACnD,GAAIuR,SAAUh9B,KAAK2nB,MAKnB,IAJAnlB,KAAOxC,KAAKwF,KAAK,YACjBxF,KAAKooB,OAGc,MAAfpoB,KAAK6R,MAAe,CACtBrP,KAAOA,KAAKw6B,SAAS,EACrB,IAAIx3B,MAAOxF,KAAKwF,KAAK,gBACjBL,OAASnF,KAAKooB,OAAOyN,WACzB71B,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzB5lB,KAAOgD,KAAKhD,KAAM2C,YAElB3C,MAAOw6B,YAGTx6B,MAAOxC,KAAK61B,WAEd71B,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzBpkB,OAASA,OAAO,WAAYxB,MAAM,GAAO,OAKtC,IAAIxC,KAAK6R,QAAU7R,KAAKmc,IAAIoR,aAC/BvpB,OAAShE,KAAKooB,OAAOwN,eAAc,GAAO,GAAO,GACjD51B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,WAKtB,IAAIpoB,KAAK6R,QAAU7R,KAAKmc,IAAIyP,WAAY,CAI3C,GAHA5nB,OAAShE,KAAKi9B,sBAAqB,GAGhB,MAAfj9B,KAAK6R,MAAe,CACtB,GAAIrM,MAAOxF,KAAKwF,KAAK,gBACjBL,OAASnF,KAAKooB,OAAO8U,wBACzBl9B,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzBpkB,OAASwB,KAAKxB,OAAQmB,QAIxB,GAAInF,KAAK6R,QAAU7R,KAAKmc,IAAIiP,kBAAmB,CAC7C,GAAI5lB,MAAOxF,KAAKwF,KAAK,kBACjBf,KAAOzE,KAAKwF,KAAK,WACrBxF,MAAKooB,OAAOmL,OAAOvzB,KAAKmc,IAAIoP,SAC5B,IAAI/oB,MAAOxC,KAAK2nB,MAChB3nB,MAAKooB,OACLpkB,OAASwB,KAAKxB,OAAQS,KAAKjC,YAIxB;AACLxC,KAAKuzB,OAAOvzB,KAAKmc,IAAI0P,0BACrB,IAAIlf,OAAQ3M,KAAK2nB,MACjB3nB,MAAKooB,OAELpkB,OAASA,OAAO,UAAU,EAAO2I,OAGnC,MAAO3I,SAKRq0B,qBAAsB,SAAS9E,QAC9B,GAAI/tB,MAAOxF,KAAKwF,KAAK,YAAamH,SAAYtI,KAAO,IAWrD,KAREA,KADa,MAAXkvB,OACKvzB,KAAK8xB,IAAIqL,SAAS9rB,WACL,MAAXkiB,OACFvzB,KAAK8xB,IAAIqL,SAAS/rB,YAElBpR,KAAK8xB,IAAIqL,SAAS7rB,aAIrBtR,KAAK6R,QAAU0hB,QAAUvzB,KAAK6R,QAAU7R,KAAKsc,KACjD3P,MAAMpL,KAAKvB,KAAK+8B,4BASlB,OANA/8B,MAAKuzB,OAAOA,SAAWvzB,KAAKooB,OAC5B5iB,KAAOA,KAAKmH,MAAOtI,MAEfkvB,SAAWvzB,KAAKmc,IAAIgR,gBACtB3nB,KAAK6N,MAAQrT,KAAKqD,MAAMypB,eAEnBtnB,MAKRq3B,mBAAoB,WACnB,GAAI74B,QAAShE,KAAKwF,KAAK,SACnBhD,KAAOxC,KAAK2nB,MAEhB,OADA3nB,MAAKooB,OACEpkB,OAAOxB,aAIZ46B,KAAK,SAAS7+B,QAAQkB,OAAOJ,SAMnCI,OAAOJ,SAOL+7B,oBAAqB,WAEnB,IADA,GAAIp3B,WACEhE,KAAK6R,QAAU7R,KAAKsc,KAAsB,MAAftc,KAAK6R,OAAe,CACnD,GAAIwrB,WAAYr9B,KAAKk7B,oBACjBmC,aACEh8B,MAAM+xB,QAAQiK,WAChBr5B,OAASA,OAAOvD,OAAO48B,WAEvBr5B,OAAOzC,KAAK87B,YAIlB,MAAOr5B,SAYRk3B,mBAAoB,WACnB,OAAOl7B,KAAK6R;AACV,IAAK7R,MAAKmc,IAAIgC,WACZ,MAAOne,MAAK42B,eAAc,GAAO,EAEnC,KAAK52B,MAAKmc,IAAImI,WACd,IAAKtkB,MAAKmc,IAAIqI,QACZ,GAAIyR,MAAOj2B,KAAKw2B,kBAChB,OAAIx2B,MAAK6R,QAAU7R,KAAKmc,IAAI6F,QACnBhiB,KAAKg2B,WAAWC,OAEvBj2B,KAAK6zB,MAAM7zB,KAAKmc,IAAI6F,SACpBhiB,KAAKooB,OACE,KAEX,KAAKpoB,MAAKmc,IAAI6F,QACZ,MAAOhiB,MAAKg2B,YAAY,EAAG,EAAG,GAChC,KAAKh2B,MAAKmc,IAAI+F,YACZ,MAAOliB,MAAKw3B,gBACd,KAAKx3B,MAAKmc,IAAIgG,QACZ,MAAOniB,MAAK23B,YACd,KAAK33B,MAAKmc,IAAIqH,MACZ,MAAOxjB,MAAKs7B,oBACd,KAAKt7B,MAAKmc,IAAIkC,QACZ,MAAOre,MAAKooB,OAAOkV,iBACrB,KAAKt9B,MAAKmc,IAAImH,YACZ,MAAOtjB,MAAKi7B,gBACd,KAAKj7B,MAAKmc,IAAI+H,gBACZ,GAAIlgB,QAAShE,KAAKwF,KAAK,OAKvB,OAJIxF,MAAKooB,OAAOmL,OAAO,MAAMvzB,KAAKooB,OAC9BpoB,KAAKuzB,OAAO,MAAMvzB,KAAKooB,OAC3BpoB,KAAKuzB,OAAO,KACZvzB,KAAKqD,MAAMgkB,MAAO,EACXrjB,OAAOhE,KAAKqD,MAAM4B,OAAOC,UAC9BlF,KAAKqD,MAAM8B,QAEf,SACE,MAAOnF,MAAKw6B,mBASjB+C,sBAAuB,WAEtB,IADA,GAAIv5B,WACEhE,KAAK6R,OAAS7R,KAAKsc,KAAsB,MAAftc,KAAK6R,OAAe,CAClD,GAAIwrB,WAAYr9B,KAAKu6B,sBACjB8C,aACEh8B,MAAM+xB,QAAQiK,WAChBr5B,OAASA,OAAOvD,OAAO48B,WAEvBr5B,OAAOzC,KAAK87B;CAIlB,MAAOr5B,SAQRs5B,gBAAiB,WAChB,GAAIt5B,QAAShE,KAAKk3B,UAAU,WAC1Bl3B,KAAKuzB,OAAOvzB,KAAKmc,IAAIoP,SACrB,IAAIvnB,QAAShE,KAAKwF,KAAK,YACnBhD,KAAOxC,KAAK2nB,MAChB,OAAI3nB,MAAKooB,OAAOmL,OAAO,KACdvvB,OAAOxB,KAAMxC,KAAKooB,OAAOyN,aAGzB7xB,OAAOxB,KAAM,OAErB,KAAK,EAER,OADAxC,MAAKg0B,uBACEhwB,QASRw5B,kBAAmB,WAElB,IADA,GAAIx5B,WACEhE,KAAK6R,OAAS7R,KAAKsc,KAAsB,MAAftc,KAAK6R,OAAe,CAClD7R,KAAKuzB,OAAOvzB,KAAKmc,IAAIoP,SACrB,IAAI/oB,MAAOxC,KAAK2nB,OAAO9hB,aAMvB,IALI7F,KAAKooB,OAAOmL,OAAO,KACrBvvB,OAAOxB,MAAQxC,KAAKooB,OAAOyN,YAE3B7xB,OAAOxB,MAAQ,KAEE,MAAfxC,KAAK6R,MAAe,KACxB7R,MAAKooB,OAEP,MAAOpkB,SAQRu2B,qBAAsB,WACrB,OAAOv6B,KAAK6R,OACV,IAAK7R,MAAKmc,IAAIgC,WACZ,MAAOne,MAAK42B,eAAc,GAAO,EAEnC,KAAK52B,MAAKmc,IAAImI,WACd,IAAKtkB,MAAKmc,IAAIqI,QACZ,GAAIyR,MAAOj2B,KAAKw2B,kBAChB,OAAIx2B,MAAK6R,QAAU7R,KAAKmc,IAAI6F,QACnBhiB,KAAKg2B,WAAWC,OAEvBj2B,KAAK6zB,MAAM7zB,KAAKmc,IAAI6F,SAEpBhiB,KAAKooB,OACE,KAEX,KAAKpoB,MAAKmc,IAAI6F,QACZ,MAAOhiB,MAAKg2B,YAAY,EAAG,EAAG,GAChC,KAAKh2B,MAAKmc,IAAI+F,YACZ,MAAOliB,MAAKw3B,gBACd,KAAKx3B,MAAKmc,IAAIgG,QACZ,MAAOniB,MAAK23B;AACd,IAAK33B,MAAKmc,IAAI+H,gBACZlkB,KAAKqzB,WACH,8DAGF,IAAI7tB,MAAOxF,KAAKwF,KAAK,OAOrB,OANAxF,MAAKooB,OAAOmL,OAAO,MAAQvzB,KAAKooB,OAChCpoB,KAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzB5iB,KAAOA,KAAKxF,KAAKqD,MAAM4B,OAAOC,UAC5BlF,KAAKqD,MAAM8B,SAEbnF,KAAKuzB,OAAO,MAAQvzB,KAAKooB,OAClB5iB,IACT,SACE,MAAOxF,MAAKw6B,mBAMjBA,eAAgB,WAEf,OAAOx6B,KAAK6R,OAEV,IAAK,IAAK,MAAO7R,MAAKu5B,iBAAgB,EAEtC,KAAKv5B,MAAKmc,IAAI8C,KAAM,MAAOjf,MAAKooB,OAAO+R,SAEvC,KAAKn6B,MAAKmc,IAAI2E,SAAU,MAAO9gB,MAAKy9B,aAEpC,KAAKz9B,MAAKmc,IAAI4D,MAAO,MAAO/f,MAAKooB,OAAOyS,UAExC,KAAK76B,MAAKmc,IAAIgE,UAAW,MAAOngB,MAAKooB,OAAO0S,cAE5C,KAAK96B,MAAKmc,IAAIsD,QAAS,MAAOzf,MAAKooB,OAAOsS,YAE1C,KAAK16B,MAAKmc,IAAI0D,KAAM,MAAO7f,MAAKooB,OAAOwS,SAEvC,KAAK56B,MAAKmc,IAAImM,UAAW,MAAOtoB,MAAKi3B,cAErC,KAAKj3B,MAAKmc,IAAIoM,cAAe,MAAOvoB,MAAKg3B,kBAEzC,KAAKh3B,MAAKmc,IAAIoC,SACZ,GAAIva,QAAShE,KAAKwF,KAAK,UAAWiT,KAAO,IAKzC,OAJKzY,MAAKooB,OAAOmM,GAAG,SAClB9b,KAAOzY,KAAK61B,aAEd71B,KAAKg0B,uBACEhwB,OAAOyU,KAGhB,KAAKzY,MAAKmc,IAAImF;AACd,IAAKthB,MAAKmc,IAAIqF,WACZ,GAAIxd,QAAShE,KAAKwF,KAChBxF,KAAK6R,QAAU7R,KAAKmc,IAAIqF,WAAa,WAAa,SACjDxU,MAAQ,IAMX,OALAhN,MAAKooB,OACc,MAAfpoB,KAAK6R,OAAiB7R,KAAK6R,QAAU7R,KAAKmc,IAAIkQ,cAChDrf,MAAQhN,KAAK61B,aAEf71B,KAAKg0B,uBACEhwB,OAAOgJ,MAEhB,KAAKhN,MAAKmc,IAAIyH,SACZ,GAAI5f,QAAShE,KAAKwF,KAAK,UACnBmG,MAAQ3L,KAAKooB,OAAO8O,UAAUl3B,KAAKi9B,qBAAsB,IAE7D,OADAj9B,MAAKg0B,uBACEhwB,OAAO2H,MAEhB,KAAK3L,MAAKmc,IAAIiI,SACZ,GAAIsZ,UAAW19B,KAAK6R,MAAO7R,KAAKqD,MAAM0kB,YAClC/jB,OAAShE,KAAKwF,KAAK,SACvB,IAAIxF,KAAKooB,OAAOvW,QAAU7R,KAAKmc,IAAIsS,eAAgB,CAEjDzuB,KAAKqD,MAAM+Y,OAAO7a,KAAKm8B,QACvB,IAAIjlB,MAAOzY,KAAKooB,OAAOyN,WAEvB,OADA71B,MAAKuzB,OAAO,MAAQvzB,KAAKizB,mBAClBxa,KAET,GAAIzY,KAAK6R,QAAU7R,KAAKmc,IAAIgC,WAC1B,MAAOne,MAAK42B,eAAc,GAAO,EAAG,EAAG,GAEzC,IAAIjrB,OAAQ3L,KAAK29B,4BAEjB,OADA39B,MAAKg0B,uBACEhwB,OAAO2H,MAEhB,KAAK3L,MAAKmc,IAAIyF,OACZ,GAAI5d,QAAShE,KAAKwF,KAAK,QACnBpE,KAAOpB,KAAKooB,OAAO8O,UAAUl3B,KAAK61B,UAAW,IAEjD,OADA71B,MAAKg0B,uBACEhwB,OAAO5C,KAEhB,KAAKpB,MAAKmc,IAAIgO,cACZ,GAAInmB,QAAShE,KAAKwF,KAAK,UAAWmH,MAAQ3M,KAAK2nB;AAE/C,MADA3nB,MAAKooB,OACEpkB,OAAO2I,MAEhB,KAAK3M,MAAKmc,IAAI6I,QACZ,GAAIhhB,QAAShE,KAAKwF,KAAK,QACvBxF,MAAKooB,OAAOmL,OAAO,MAAQvzB,KAAKooB,MAChC,IAAIzc,OAAQ3L,KAAKk3B,UAAUl3B,KAAK41B,cAAe,IAG/C,OAFA51B,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzBpoB,KAAKuzB,OAAO,MAAQvzB,KAAKizB,mBAClBjvB,OAAO2H,MAEhB,KAAK3L,MAAKmc,IAAIoE,UACZ,GACE9b,MAEAwL,KAHEjM,OAAShE,KAAKwF,KAAK,WAErB8H,OAKF,IAHAtN,KAAKooB,OAAOmL,OAAO,MAAQvzB,KAAKooB,OAChC3jB,KAAOzE,KAAKw9B,oBACZx9B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,OACN,MAAfpoB,KAAK6R,MAAe,CAEtB,IADA7R,KAAKizB,mBACCjzB,KAAK6R,OAAS7R,KAAKsc,KAAOtc,KAAK6R,QAAU7R,KAAKmc,IAAIsE,cAEtDnT,KAAK/L,KAAKvB,KAAKk7B,qBAEjBl7B,MAAKuzB,OAAOvzB,KAAKmc,IAAIsE,eAAiBzgB,KAAKooB,OAC3CpoB,KAAKg0B,uBACL/jB,KAAOjQ,KAAK8xB,IAAIxR,QAAQpQ,eACnB,IAAmB,MAAflQ,KAAK6R,MAAe,CAE7B,IADA7R,KAAKizB,mBACCjzB,KAAK6R,OAAS7R,KAAKsc,KAAsB,MAAftc,KAAK6R,OAEnCvE,KAAK/L,KAAKvB,KAAKk7B,qBAEjBl7B,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzBnY,KAAOjQ,KAAK8xB,IAAIxR,QAAQnQ,eACnB,CAEL,IADAnQ,KAAKuzB,OAAO,MAAQvzB,KAAKizB,mBACnBjzB,KAAK6R,OAAS7R,KAAKsc,KAAOtc,KAAK6R,QAAU7R,KAAKmc,IAAIoE,WAEtDjT,KAAK/L,KAAKvB,KAAKk7B,qBAEjBjrB,MAAOjQ,KAAK8xB,IAAIxR,QAAQlQ;CAE1B,MAAOpM,QAAOS,KAAM6I,KAAM2C,KAE5B,KAAKjQ,MAAKmc,IAAIsC,MACZ,MAAOze,MAAK49B,UAEd,KAAK59B,MAAKmc,IAAI4C,QACZ,GAAI/a,QAAShE,KAAKwF,KAAK,SACnBiT,KAAOzY,KAAKooB,OAAOyN,WAEvB,OADA71B,MAAKg0B,uBACEhwB,OAAOyU,KAEhB,KAAK,IACL,IAAKzY,MAAKmc,IAAIkQ,YAEZ,MADArsB,MAAKooB,OACE,IAET,KAAKpoB,MAAKmc,IAAIoP,SACZ,GAAImS,UAAW19B,KAAK6R,MAAO7R,KAAKqD,MAAM0kB,YAClC1U,MAAQrT,KAAK2nB,MAEjB,IAA0B,MAAtB3nB,KAAKooB,OAAOvW,MAAe,CAC7B,GAAI7N,QAAShE,KAAKwF,KAAK,QAEvB,OADAxF,MAAKooB,OACEpkB,OAAOqP,OAIhBrT,KAAKqD,MAAM+Y,OAAO7a,KAAKm8B,QACvB,IAAIjlB,MAAOzY,KAAKooB,OAAOyN,WAEvB,OADA71B,MAAKg0B,uBACEvb,IAET,KAAKzY,MAAKmc,IAAIuF,OACZ,GAAI1d,QAAShE,KAAKwF,KAAK,QAAS6N,MAAQ,IAKxC,OAJIrT,MAAKooB,OAAOmL,OAAOvzB,KAAKmc,IAAIoP,YAC9BlY,MAAQrT,KAAK2nB,OACb3nB,KAAKooB,OAAO4L,wBAEPhwB,OAAOqP,MAEhB,SACE,GAAIoF,MAAOzY,KAAK61B,WAEhB,OADA71B,MAAKg0B,uBACEvb,OAQZ8gB,gBAAiB,SAASsE,KACzB,GAAI75B,QAAShE,KAAKwF,KAAK,QACvBxF,MAAKuzB,OAAO,MAAQvzB,KAAKizB,kBACzB,IAAI3lB,MAAOuwB,IACT79B,KAAKo7B,sBACHp7B,KAAKu9B,uBAGT,OADAv9B,MAAKuzB,OAAO,MAAQvzB,KAAKizB,mBAClBjvB,OAAO,KAAMsJ;QAIlBwwB,KAAK,SAASv/B,QAAQkB,OAAOJ,SAMnC,YAEAI,QAAOJ,SASLo+B,YAAa,WACXz9B,KAAKuzB,OAAOvzB,KAAKmc,IAAI2E,WAAa9gB,KAAKooB,MACvC,IAAkC5jB,MAAM8I,KAAM5B,UAA1C1H,OAAShE,KAAKwF,KAAK,SAMvB,OALAxF,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzB5jB,KAAOxE,KAAK61B,YACZ71B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzB1c,UAA4B,MAAf1L,KAAK6R,MAClBvE,KAAOtN,KAAK+9B,wBACL/5B,OAAOQ,KAAM8I,KAAM5B,YAQ3BqyB,sBAAuB,WAEtB,GAAIxK,QAAS,KACXvvB,OAAShE,KAAKwF,KAAK,SACnBmG,QAkBF,KAjBmB,MAAf3L,KAAK6R,MACP0hB,OAAS,IACe,MAAfvzB,KAAK6R,MACd0hB,OAASvzB,KAAKmc,IAAI6E,YAElBhhB,KAAKuzB,QAAQ,IAAK,MAIM,MAAtBvzB,KAAKooB,OAAOvW,OACd7R,KAAKooB,OAGHpoB,KAAK6R,QAAU7R,KAAKmc,IAAIkQ,aAC1BrsB,KAAKooB,OAGDpoB,KAAK6R,QAAU7R,KAAKsc,KAAOtc,KAAK6R,QAAU0hB,QAC9C5nB,MAAMpK,KAAMvB,KAAKg+B,eAAezK,QAOlC,OAJAvzB,MAAKuzB,OAAOA,SAAWvzB,KAAKooB,OACxBmL,SAAWvzB,KAAKmc,IAAI6E,aACtBhhB,KAAKg0B,uBAEAhwB,OAAO,KAAM2H,QAOrBqyB,eAAgB,SAASC,WACxB,GAAIj6B,QAAShE,KAAKwF,KAAK,QAAShB,KAAO,KAAM8I,KAAO,KAAM3B,QAW1D,KAVI3L,KAAK6R,QAAU7R,KAAKmc,IAAI+E,OAC1B1c,KAAOxE,KAAKooB,OAAOyN,YACV71B,KAAK6R,QAAU7R,KAAKmc,IAAIiF,UAEjCphB,KAAKooB,OAELpoB,KAAKuzB,QAAQvzB,KAAKmc,IAAI+E,OAAQlhB,KAAKmc,IAAIiF;AAEzCphB,KAAKuzB,QAAQ,IAAK,OAASvzB,KAAKooB,OAChC9a,KAAOtN,KAAKwF,KAAK,SAEfxF,KAAK6R,OAAS7R,KAAKsc,KAChBtc,KAAK6R,QAAUosB,WACfj+B,KAAK6R,QAAU7R,KAAKmc,IAAI+E,QACxBlhB,KAAK6R,QAAU7R,KAAKmc,IAAIiF,WAE3BzV,MAAMpK,KAAKvB,KAAKu6B,uBAElB,OAAOv2B,QACLQ,KAAMmH,MAAMpM,OAAS,EAAI+N,KAAK,KAAM3B,OAAS,aAK7CuyB,KAAK,SAAS3/B,QAAQkB,OAAOJ,SAMnCI,OAAOJ,SAYLu+B,SAAU,WACR59B,KAAKuzB,OAAOvzB,KAAKmc,IAAIsC,MACrB,IAEEnR,MAFEtJ,OAAShE,KAAKwF,KAAK,OACrBkV,OAAS,KAETD,UAIF,KAFAnN,KAAOtN,KAAKooB,OAAOoS,iBAEbx6B,KAAKs0B,iBAAiBziB,QAAU7R,KAAKmc,IAAIwC,SAAS,CACtD,GAAIwf,MAAOn+B,KAAKwF,KAAK,SAAUf,QAAWkJ,SAAW,IACrD3N,MAAKooB,OAAOmL,OAAO,MAAQvzB,KAAKooB,OAChC3jB,KAAOzE,KAAKk3B,UACVl3B,KAAKq2B,oBAAqB,KAAK,GAEjC1oB,SAAW3N,KAAK41B,eAAc,GAAM,GAAO,GAC3C51B,KAAKuzB,OAAO,KACZ9Y,QAAQlZ,KACN48B,KAAKn+B,KAAKooB,OAAOoS,iBAAkB/1B,KAAMkJ,WAM7C,MAHI3N,MAAK6R,QAAU7R,KAAKmc,IAAI0C,YAC1BnE,OAAS1a,KAAKooB,OAAOoS,kBAEhBx2B,OAAOsJ,KAAMmN,QAASC,eAI3B0jB,KAAK,SAAS7/B,QAAQkB,OAAOJ,SAOnC,YAEAI,QAAOJ,SAMLs7B,gBAAiB,SAAS9oB,OACxB,GAAIvE,MAAOtN,KAAKwF,KAAK,SAAUmG,QAE/B,KADI3L,KAAKuzB,OAAO,MAAMvzB,KAAKooB,OACrBpoB,KAAK6R,OAAS7R,KAAKsc,KAAOtc,KAAK6R,QAAUA,OAC7ClG,MAAMpK,KAAKvB,KAAKu6B;AAIlB,MAFIv6B,MAAKuzB,OAAO1hB,QAAQ7R,KAAKooB,OAC7BpoB,KAAKg0B,uBACE1mB,KAAK,KAAM3B,QASnBurB,UAAW,SAASiH,KAAME,UAAWC,wBACpC,GAAIt6B,UAOJ,IALIhE,KAAK6R,OAASwsB,YACZC,wBAAwBt6B,OAAOzC,KAAK,IACxCvB,KAAKooB,QAGe,kBAAX,OACT,EAEE,IADApkB,OAAOzC,KAAK48B,KAAK18B,MAAMzB,UACnBA,KAAK6R,OAASwsB,UAChB,YAEIr+B,KAAKooB,OAAOvW,OAAS7R,KAAKsc,SAC7B,CACL,IAAItc,KAAKuzB,OAAO4K,MAGd,QAEF,KAJEn6B,OAAOzC,KAAKvB,KAAK2nB,QAIZ3nB,KAAKooB,OAAOvW,OAAS7R,KAAKsc,KAC3Btc,KAAK6R,OAASwsB,WAEdr+B,KAAKooB,OAAOvW,OAASssB,MACzBn6B,OAAOzC,KAAKvB,KAAK2nB,QAGrB,MAAO3jB,SAkBRsyB,eAAgB,WACf,MAAOt2B,MAAKk3B,UACVl3B,KAAKq2B,oBAAqB,KAAK,IAmBlCsH,2BAA4B,WAC3B,MAAO39B,MAAKk3B,UAAU,WACpB,GAAI1xB,MAAOxF,KAAKwF,KAAK,UAEnBmI,SAAW3N,KAAKwF,KAAK,WAEvB,IAAIxF,KAAKuzB,OAAOvzB,KAAKmc,IAAIyP,YAAa,CACpC,GAAIppB,MAAOxC,KAAK2nB,OAAOziB,UAAU,EACjClF,MAAKooB,OACLza,SAAWA,SAASnL,MAAM,GAAO,OAEjCmL,UAAWA,SAAS,QAAQ,GAAO,EAErC,OAAmB,MAAf3N,KAAK6R,MACArM,KAAKmI,SAAU3N,KAAKooB,OAAOyN,aAE3BloB,UAER,YAKD4wB,KAAK,SAAShgC,QAAQkB,OAAOJ;AAMnC,YACAI,QAAOJ,SAiBLu2B,cAAe,SAAS4I,UAAWrB,SAAUruB,OAC3C,GAAI9K,OASJ,IANK8K,OAAwB,MAAf9O,KAAK6R,QACjB/C,OAAQ,EACR9O,KAAKooB,QAIHpoB,KAAKu0B,IAAIv0B,KAAKmc,IAAIyP,WAAY,MAChC5nB,OAAShE,KAAKy+B,wBAAwBtB,SAAUruB,WAC3C,IAAI9O,KAAKu0B,IAAIv0B,KAAKmc,IAAIkS,eAAgBruB,KAAKmc,IAAIoP,SAAUvrB,KAAKmc,IAAImH,cAAe,CACtFtf,OAAShE,KAAKwF,MACd,IAAIhD,MAAOxC,KAAKq2B,qBAChB,IACEr2B,KAAK6R,OAAS7R,KAAKmc,IAAIsS,gBACN,KAAdzuB,KAAK6R,MACR,CAEA,GAAI6sB,SAAUl8B,KAAKA,KAAKqD,aAEtB7B,QADc,SAAZ06B,QACO16B,OAAO,WAAW,GACN,UAAZ06B,QACA16B,OAAO,WAAW,GAGlBA,OAAO,WAAYxB,UAG9BwB,QAASxB,SAEFxC,MAAK6R,QAAU7R,KAAKmc,IAAIiI,UACjCpgB,OAAShE,KAAKwF,KAAK,YACnBxF,KAAKooB,OACLpkB,OAASA,OAAO,WAEhBhE,KAAKuzB,OAAO,WAQd,OAJIvzB,MAAK6R,QAAU7R,KAAKmc,IAAIsS,iBAC1BzqB,OAAShE,KAAKi5B,mBAAmBj1B,OAAQm5B,WAGpCn9B,KAAKk4B,8BAA8Bl0B,OAAQw6B,UAAWrB,WAI9DlE,mBAAoB,SAASx0B,KAAM04B,UAClC,GAAIn5B,QAAShE,KAAKwF,KAAK,gBACnBL,OAAS,IACb,IAAInF,KAAKooB,OAAOmM,IAAIv0B,KAAKmc,IAAIyP,WAAY,MACvCzmB,OAASnF,KAAKy+B,wBAAwBtB,UAAU,OAC3C,IACLn9B,KAAK6R,QAAU7R,KAAKmc,IAAIoP,UACrBvrB,KAAK6R,QAAU7R,KAAKmc,IAAI6F,QAC3B;AACA7c,OAASnF,KAAKwF,KAAK,WACnB,IAAIhD,MAAOxC,KAAK2nB,MAChB3nB,MAAKooB,OACLjjB,OAASA,OAAO3C,UACX,CACLxC,KAAK6zB,OAAO7zB,KAAKmc,IAAIyP,WAAY5rB,KAAKmc,IAAIoP,WAE1CpmB,OAASnF,KAAKwF,KAAK,WACnB,IAAIhD,MAAOxC,KAAK2nB,MAChB3nB,MAAKooB,OACLjjB,OAASA,OAAO3C,MAElB,MAAOwB,QAAOS,KAAMU,SAGrB+yB,8BAA+B,SAASl0B,OAAQw6B,UAAWrB,UAC1DwB,oBACA,KAAM3+B,KAAK6R,OAAS7R,KAAKsc,KACvB,OAAOtc,KAAK6R,OACV,IAAK,IACH,GAAI2sB,UAEF,MAAOx6B,OAEPA,QAAShE,KAAKwF,KAAK,QACjBxB,OAAShE,KAAKo4B,8BAGlB,MACF,KAAK,IACH,GAAI5yB,MAAOxF,KAAKwF,KAAK,eACrBxF,MAAKooB,MACL,IAAIjjB,SAAS,CACTg4B,WACFh4B,OAASnF,KAAKk9B,yBACdl9B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,QAGN,MAAfpoB,KAAK6R,OACP1M,OAASnF,KAAK61B,YACd71B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,QAEzBpoB,KAAKooB,OAGTpkB,OAASwB,KAAKxB,OAAQmB,OACtB,MACF,KAAKnF,MAAKmc,IAAIiP,kBACZ,GAAI5lB,MAAOxF,KAAKwF,KAAK,kBACjBf,KAAO,IACX,QAAOzE,KAAKooB,OAAOvW,OACjB,IAAK7R,MAAKmc,IAAIoP,SACZ9mB,KAAOzE,KAAKwF,KAAK,WACjB,IAAIhD,MAAOxC,KAAK2nB,MAGhB,IAFA3nB,KAAKooB,OACL3jB,KAAOA,KAAKjC,MACRxC,KAAK6R,QAAU7R,KAAKmc,IAAIyP,WAAY,CACtC,GAAIxU,OAAQpX,KAAKwF,KAAK;AACtBhD,KAAOxC,KAAK2nB,OAAOziB,UAAU,GAC7BlF,KAAKooB,OACL3jB,KAAOzE,KAAKwF,KAAK,aACdf,KAAM2S,MAAM5U,MAAM,GAAO,IAC1B,UAEEiC,KAAK0R,KAAO1R,KAAKkI,MAAM,GAAGwJ,MAC5B1R,KAAK0R,IAAIvR,MAAQH,KAAKkI,MAAM,GAAGwJ,IAAIvR,WAEhC,IAAmB,MAAf5E,KAAK6R,MAAe,CAC7B,GAAI4G,MAAOzY,KAAKooB,OAAOyN,WACvB71B,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzB3jB,KAAOzE,KAAKwF,KAAK,aACdf,KAAMgU,MACP,UAEEhU,KAAK0R,KAAO1R,KAAKkI,MAAM,GAAGwJ,MAC5B1R,KAAK0R,IAAIvR,MAAQH,KAAKkI,MAAM,GAAGwJ,IAAIvR,OAGvC,KACF,KAAK5E,MAAKmc,IAAIyP,WACZnnB,KAAOzE,KAAKwF,KAAK,WACjB,IAAIhD,MAAOxC,KAAK2nB,OAAOziB,UAAU,EACjClF,MAAKooB,OACL3jB,KAAOA,KAAKjC,MAAM,GAAO,EACzB,MACF,KAAK,IACHxC,KAAKooB,OAAOmL,QAAQ,IAAKvzB,KAAKmc,IAAIyP,aACf,MAAf5rB,KAAK6R,OAEPpN,KAAOzE,KAAKooB,OAAOyN,YACnB71B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,QAGzB3jB,KAAOzE,KAAK61B,WAEd,MACF,KAAK,IACHpxB,KAAOzE,KAAKooB,OAAOyN,YACnB71B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,MACzB,MACF,SACEpoB,KAAK6zB,OAAO7zB,KAAKmc,IAAIoP,SAAUvrB,KAAKmc,IAAIyP,aAExCnnB,KAAOzE,KAAKwF,KAAK,WACjB,IAAIhD,MAAOxC,KAAK2nB,MAChB3nB,MAAKooB,OACL3jB,KAAOA,KAAKjC,MAGhBwB,OAASwB,KAAKxB,OAAQS,KACtB,MACF,SACE,KAAMk6B,qBAGZ,MAAO36B,SAKRk5B,uBAAwB,WACvB,GAAI/3B,QAASnF,KAAKwF,MAClB,IAAIxF,KAAK6R,QAAU7R,KAAKmc,IAAIoP,SAAU;AACpC,GAAI5D,MAAO3nB,KAAK2nB,OACZiX,WAAyB,MAAZjX,KAAK,EACtBA,MAAOA,KAAKziB,UAAU,EAAGyiB,KAAKpoB,OAAS,GACvCS,KAAKooB,OACLjjB,OAASA,OACP,SAAUy5B,WAAY5+B,KAAK08B,sBAAsB/U,WAE9C,IAAI3nB,KAAK6R,QAAU7R,KAAKmc,IAAIwP,aAAc,CAC/C,GAAIkT,KAAM7+B,KAAK2nB,MACf3nB,MAAKooB,OACLjjB,OAASA,OAAO,SAAU05B,SACrB,IAAI7+B,KAAK6R,QAAU7R,KAAKmc,IAAIyP,WAAY,CAC7C,GAAIppB,MAAOxC,KAAK2nB,OAAOziB,UAAU,EACjClF,MAAKooB,OACLjjB,OAASA,OAAO,WAAY3C,MAAM,GAAO,OACpC,CACLxC,KAAKuzB,QACHvzB,KAAKmc,IAAIoP,SACTvrB,KAAKmc,IAAIwP,aACT3rB,KAAKmc,IAAIyP,YAGX,IAAIjE,MAAO3nB,KAAK2nB,MAChB3nB,MAAKooB,OACLjjB,OAASA,OAAO,UAAU,EAAOwiB,MAEnC,MAAOxiB,SAaRs5B,wBAAyB,SAAStB,SAAUruB,OAE3C,IADA,GAAI9K,QAAShE,KAAKi9B,qBAAqBnuB,OACjC9O,KAAK6R,OAAS7R,KAAKsc,KAAK,CAC5B,GAAI9W,MAAOxF,KAAKwF,MAChB,IAAkB,KAAdxF,KAAK6R,MAAc,CACrB,GAAI1M,QAAS,IAEXA,QADEg4B,SACOn9B,KAAKooB,OAAO8U,yBAEU,MAAtBl9B,KAAKooB,OAAOvW,MAAgB,KAAO7R,KAAK81B,kBAEnD91B,KAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzBpkB,OAASwB,KAAK,eAAgBxB,OAAQmB,YACjC,CAAA,GAAkB,KAAdnF,KAAK6R,OAAiBsrB,SAI1B,KAHL,IAAIh4B,QAASnF,KAAKooB,OAAOyN,WACzB71B,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzBpkB,OAASwB,KAAK,eAAgBxB,OAAQmB;EAG1C,MAAOnB,SAORi5B,qBAAsB,SAASnuB,OAC9B,GAAI9K,QAAShE,KAAKwF,KAAK,WACvB,IAAIxF,KAAKuzB,QAAQvzB,KAAKmc,IAAIyP,WAAY,OAAS5rB,KAAK6R,QAAU7R,KAAKmc,IAAIyP,WAAY,CAEjF,GAAIppB,MAAOxC,KAAK2nB,OAAOziB,UAAU,EACjClF,MAAKooB,OACLpkB,OAASA,OAAOxB,KAAMsM,OAAO,OAI7B,QAFmB,MAAf9O,KAAK6R,OAAe7R,KAAKooB,OAEtBpoB,KAAK6R,OACV,IAAK,IACH,GAAI4G,MAAOzY,KAAKooB,OAAOyN,WACvB71B,MAAKuzB,OAAO,MAAQvzB,KAAKooB,OACzBpkB,OAASA,OAAOyU,KAAM3J,OAAO,EAC7B,MACF,KAAK,IACH9K,OAASA,OAAOhE,KAAKi9B,sBAAqB,GAAQnuB,MAClD,MACF,KAAK9O,MAAKmc,IAAIyP,WACZ,GAAIppB,MAAOxC,KAAK2nB,OAAOziB,UAAU,GAC7BM,KAAOxF,KAAKwF,KAAK,WACrBxF,MAAKooB,OACLpkB,OAASA,OAAOwB,KAAKhD,MAAM,GAAO,GAAQsM,OAAO,EACjD,MACF,SACE9O,KAAK6zB,OAAO,IAAK,IAAK7zB,KAAKmc,IAAIyP,YAE/B,IAAIppB,MAAOxC,KAAK2nB,MAChB3nB,MAAKooB,OACLpkB,OAASA,OAAOxB,KAAMsM,OAAO,GAGnC,MAAO9K,eAIL86B,KAAK,SAASvgC,QAAQkB,OAAOJ,SAQnCI,OAAOJ,SACL2pB,QACEuM,IAAK,kBACLQ,IAAK,QACL8B,IAAK,4BACLE,IAAK,oBACLoB,IAAK,WACLe,IAAK,6BACLO,IAAK,mBACLO,IAAK,eACLG,IAAK,eACLU,IAAK,UACLuB,IAAK;AACLU,IAAK,YACLI,IAAK,iBACLE,IAAK,SACLG,IAAK,YACLO,IAAK,iBACLC,IAAK,cACLC,IAAK,iBACLC,IAAK,OACLC,IAAK,OACLC,IAAK,UACLC,IAAK,UACLC,IAAK,OACLC,IAAK,QACLC,IAAK,WACLC,IAAK,UACLC,IAAK,aACLC,IAAK,WACLC,IAAK,WACLC,IAAK,WACLC,IAAK,SACLC,IAAK,gBACLC,IAAK,UACLC,IAAK,YACLC,IAAK,YACLC,IAAK,QACLC,IAAK,UACLC,IAAK,SACLC,IAAK,YACLC,IAAK,UACLC,IAAK,eACLC,IAAK,SACLC,IAAK,UACLC,IAAK,eACLC,IAAK,gBACLC,IAAK,cACLC,IAAK,cACLC,IAAK,iBACLC,IAAK,cACLC,IAAK,cACLC,IAAK,aACLC,IAAK,cACLC,IAAK,aACLC,IAAK,aACLC,IAAK,QACLC,IAAK,QACLC,IAAK,eACLC,IAAK,gBACLC,IAAK,eACLC,IAAK,gBACLC,IAAK,gBACLC,IAAK,OACLC,IAAK,OACLC,IAAK,iBACLC,IAAK,qBACLC,IAAK,aACLC,IAAK,iBACLC,IAAK,wBACLC,IAAK,wBACLC,IAAK,eACLC,IAAK,aACLC,IAAK;AACLC,IAAK,gBACLC,IAAK,eACLC,IAAK,gBACLC,IAAK,cACLC,IAAK,eACLC,IAAK,SACLC,IAAK,UACLC,IAAK,UACLC,IAAK,eACLC,IAAK,aACLC,IAAK,iBACLC,IAAK,iBACLC,IAAK,UACLC,IAAK,aACLC,IAAK,UACLC,IAAK,aACLC,IAAK,UACLC,IAAK,UACLC,IAAK,YACLC,IAAK,cACLC,IAAK,eACLC,IAAK,QACLC,IAAK,WACLC,IAAK,cACLC,IAAK,YACLC,IAAK,UACLC,IAAK,QACLC,IAAK,cACLC,IAAK,WACLC,IAAK,SACLC,IAAK,cACLC,IAAK,SACLC,IAAK,YACLC,IAAK,WACLC,IAAK,eACLC,IAAK,aACLC,IAAK,6BACLC,IAAK,YACLC,IAAK,YACLC,IAAK,SACLC,IAAK,SACLC,IAAK,QACLC,IAAK,YACLC,IAAK,aACLC,IAAK,WACLC,IAAK,SACLC,IAAK,kBACLC,IAAK,gBACLC,IAAK,YACLC,IAAK,aACLC,IAAK,aACLC,IAAK,uBACLC,IAAK,cACLC,IAAK,eACLC,IAAK,YACLC,IAAK,gBACLC,IAAK,aACLC,IAAK,aACLC,IAAK,QACLC,IAAK,cACLC,IAAK;EAEP9pB,OACE6H,gBAAiB,IACjBV,MAAO,IACPqI,0BAA2B,IAC3BT,kBAAmB,IACnBG,SAAU,IACV8B,2BAA4B,IAC5B5B,iBAAkB,IAClB8B,aAAc,IACd5B,aAAc,IACd7H,QAAS,IACTE,QAAS,IACTjB,UAAW,IACXE,eAAgB,IAChBJ,OAAQ,IACRK,UAAW,IACXE,eAAgB,IAChBE,YAAa,IACb+K,eAAgB,IAChBzN,KAAM,IACN3B,KAAM,IACNI,QAAS,IACTI,QAAS,IACTI,KAAM,IACNE,MAAO,IACPe,SAAU,IACVQ,QAAS,IACTE,WAAY,IACZjD,SAAU,IACVqF,SAAU,IACVQ,SAAU,IACVxC,OAAQ,IACRuI,cAAe,IACfnF,QAAS,IACT7E,UAAW,IACXI,UAAW,IACX9B,MAAO,IACPM,QAAS,IACT2C,OAAQ,IACR7C,UAAW,IACXF,QAAS,IACT8B,aAAc,IACdwE,OAAQ,IACRxC,QAAS,IACT6M,aAAc,IACdnB,cAAe,IACfmC,YAAa,IACb/B,YAAa,IACbmC,eAAgB,IAChBG,YAAa,IACbE,YAAa,IACbG,WAAY,IACZG,YAAa,IACbxB,WAAY,IACZM,WAAY,IACZd,MAAO,IACPnB,MAAO,IACPiD,aAAc,IACdH,cAAe,IACf1L,aAAc,IACdE,cAAe,IACfE,cAAe,IACfoK,KAAM,IACNM,KAAM,IACNlB,eAAgB,IAChBM,mBAAoB,IACpBL,WAAY,IACZM,eAAgB,IAChBO,sBAAuB;AACvBE,sBAAuB,IACvBvP,aAAc,IACdkF,WAAY,IACZG,cAAe,IACfI,cAAe,IACfE,aAAc,IACdE,cAAe,IACfE,YAAa,IACbE,aAAc,IACd5I,OAAQ,IACR8D,QAAS,IACT+L,QAAS,IACTD,aAAc,IACdzP,WAAY,IACZ8Q,eAAgB,IAChBR,eAAgB,IAChBvJ,QAAS,IACTE,WAAY,IACZpD,QAAS,IACTsC,WAAY,IACZnC,QAAS,IACTqC,QAAS,IACTpC,UAAW,IACXF,YAAa,IACbG,aAAc,IACdM,MAAO,IACPmC,SAAU,IACVF,YAAa,IACbF,UAAW,IACXrG,QAAS,IACTkE,MAAO,IACPmB,YAAa,IACbvE,SAAU,IACVI,OAAQ,IACRyB,YAAa,IACbE,OAAQ,IACRE,UAAW,IACXnB,SAAU,IACVI,aAAc,IACdV,WAAY,IACZuM,2BAA4B,IAC5BlB,UAAW,IACXD,UAAW,IACXvN,OAAQ,IACRE,OAAQ,IACRE,MAAO,IACPV,UAAW,IACXI,WAAY,IACZF,SAAU,IACVU,OAAQ,IACRiP,gBAAiB,IACjBI,cAAe,IACfnQ,UAAW,IACX4O,WAAY,IACZpD,WAAY,IACZC,qBAAsB,IACtB4D,YAAa,IACbhE,aAAc,IACdC,UAAW,IACXC,cAAe,IACfoI,WAAY,IACZhB,WAAY,IACZa,MAAO,IACPD,YAAa,IACbR,YAAa,WAIXqW,cAAc,SAAS7nC,QAAQkB,OAAOJ;AAe5C,QAASgnC,SAAQrhC,IAAKshC,IAGpB,IAFA,GAAIC,MAAO9gC,OAAO8gC,KAAKvhC,KACnBhG,EAAIunC,KAAKhnC,OACNP,KAAK,CACV,GAAIoqB,GAAImd,KAAKvnC,GACTu4B,IAAMvyB,IAAIokB,EACF,QAARmO,UACK+O,IAAGld,GACc,kBAARmO,KAChB+O,GAAGld,GAAKmO,IAAIiP,KAAKF,IACRjlC,MAAM+xB,QAAQmE,KACvB+O,GAAGld,GAAK/nB,MAAM+xB,QAAQkT,GAAGld,IAAMkd,GAAGld,GAAG3oB,OAAO82B,KAAOA,IAC3B,gBAARA,KAChB+O,GAAGld,GAAsB,gBAAVkd,IAAGld,GAAkBid,QAAQ9O,IAAK+O,GAAGld,IAAMmO,IAE1D+O,GAAGld,GAAKmO,IAGZ,MAAO+O,IA1BT,GAAIjjC,OAAQ9E,QAAQ,WAChB6E,OAAS7E,QAAQ,YACjB6d,OAAS7d,QAAQ,YACjByE,IAAMzE,QAAQ,SA2Dd2d,OAAS,SAASuqB,SACpB,MAAoB,kBAATzmC,MACF,GAAIA,MAAKymC,UAElBzmC,KAAKoc,OAASA,OACdpc,KAAKqD,MAAQ,GAAIA,OAAMrD,MACvBA,KAAK8xB,IAAM,GAAI9uB,KACfhD,KAAKoD,OAAS,GAAIA,QAAOpD,KAAKqD,MAAOrD,KAAK8xB,UACtC2U,SAA8B,gBAAZA,UACpBJ,QAAQI,QAASzmC,QAUrBkc,QAAOxW,OAAS,SAAS+gC,SACvB,MAAO,IAAIvqB,QAAOuqB,UAOpBvqB,OAAOwqB,UAAY,SAASziC,OAAQwiC,SAClC,GAAI5hC,MAAO,GAAIqX,QAAOuqB,QACtB,OAAO5hC,MAAK6hC,UAAUziC,SAQxBiY,OAAO1a,UAAUklC,UAAY,SAASziC,QAGpC,MAFAjE,MAAKqD,MAAMqZ,WAAY,EACvB1c,KAAKqD,MAAMmZ,YAAa,EACjBxc,KAAKoD,OAAOsvB,MAAMzuB,OAAQ,SAOnCiY,OAAOyqB,UAAY,SAAS1iC,OAAQ0uB,SAAU8T,SACpB,gBAAb9T,YAET8T,QAAU9T;AACVA,SAAW,UAEb,IAAI9tB,MAAO,GAAIqX,QAAOuqB,QACtB,OAAO5hC,MAAK8hC,UAAU1iC,OAAQ0uB,WAuBhCzW,OAAO1a,UAAUmlC,UAAY,SAAS1iC,OAAQ0uB,UAG5C,MAFA3yB,MAAKqD,MAAMqZ,WAAY,EACvB1c,KAAKqD,MAAMmZ,YAAa,EACjBxc,KAAKoD,OAAOsvB,MAAMzuB,OAAQ0uB,WAOnCzW,OAAO0qB,YAAc,SAAS3iC,OAAQwiC,SACpC,GAAI5hC,MAAO,GAAIqX,QAAOuqB,QACtB,OAAO5hC,MAAK+hC,YAAY3iC,SAS1BiY,OAAO1a,UAAUolC,YAAc,SAAS3iC,QACtCjE,KAAKqD,MAAMqZ,WAAY,EACvB1c,KAAKqD,MAAMmZ,YAAa,CACxB,IAAIF,KAAMtc,KAAKqD,MAAMiZ,IACjBD,MAAQrc,KAAKoc,OAAO4M,MACxBhpB,MAAKqD,MAAMwjB,SAAS5iB,OAGpB,KAFA,GAAI4N,OAAQ7R,KAAKqD,MAAM8kB,OAAS7L,IAC5BtY,UACE6N,OAASyK,KAAK,CAClB,GAAIuqB,OAAQ7mC,KAAKqD,MAAM4jB,MACnB5K,OAAMyqB,eAAej1B,SACvBg1B,OAASxqB,MAAMxK,OAAQg1B,MAAO7mC,KAAKqD,MAAMC,OAAOC,aAElDS,OAAOzC,KAAKslC,OACZh1B,MAAQ7R,KAAKqD,MAAM8kB,OAAS7L,IAE9B,MAAOtY,SAITvE,OAAOJ,QAAU6c,SAEd6qB,QAAQ,EAAEC,UAAU,GAAGC,WAAW,IAAIC,WAAW","file":"php-parser.min.js"} \ No newline at end of file diff --git a/dist/test.html b/dist/test.html deleted file mode 100644 index 3de35eec8..000000000 --- a/dist/test.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - -

-    
-  
-
\ No newline at end of file
diff --git a/docs/AST.html b/docs/AST.html
new file mode 100644
index 000000000..948c7b6a0
--- /dev/null
+++ b/docs/AST.html
@@ -0,0 +1,819 @@
+
+
+
+
+  
+  
+
+  
+      AST - Documentation
+  
+
+  
+
+  
+  
+
+  
+
+  
+  
+  
+
+  
+  
+  
+  
+
+  
+  
+  
+
+
+
+  
+    
+      
+          
+          
+      
+    
+  
+
+  
+  
+
+  
+
+  
+ +
+ + + +
+ +

+ AST +

+ + + + +
+
+ +

+ + AST + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new AST() +

+
+ + + + + +
+

The AST builder class

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
withPositions + + + + Boolean + + + + + + + +

Should locate any node (by default false)

+
withSource + + + + Boolean + + + + + + + +

Should extract the node original code (by default false)

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + +
Tutorials:
+
+
    + +
  • + AST +
  • + +
+
+ + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ prepare(kind, parser) → {function} +

+
+ + + + + +
+

Prepares an AST node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
kind + + + + String + + + | + + + null + + + + + + + +

Defines the node type +(if null, the kind must be passed at the function call)

+ +
parser + + + + Parser + + + + + + + +

The parser instance (use for extracting locations)

+ +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ resolveLocations() +

+
+ + + + + +
+

Includes locations from first & last into the target

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ resolvePrecedence() +

+
+ + + + + +
+

Check and fix precence, by default using right

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ swapLocations() +

+
+ + + + + +
+

Change parent node informations after swapping childs

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/AST.md b/docs/AST.md deleted file mode 100644 index e7b956a19..000000000 --- a/docs/AST.md +++ /dev/null @@ -1,1260 +0,0 @@ - - -## AST - -## Class hierarchy - -- [Location](#location) -- [Position](#position) -- [Node](#node) - - [Identifier](#identifier) - - [TraitUse](#traituse) - - [TraitAlias](#traitalias) - - [TraitPrecedence](#traitprecedence) - - [Entry](#entry) - - [Case](#case) - - [Label](#label) - - [Doc](#doc) - - [Error](#error) - - [Expression](#expression) - - [Array](#array) - - [Variable](#variable) - - [Variadic](#variadic) - - [ConstRef](#constref) - - [Yield](#yield) - - [YieldFrom](#yieldfrom) - - [Lookup](#lookup) - - [PropertyLookup](#propertylookup) - - [StaticLookup](#staticlookup) - - [OffsetLookup](#offsetlookup) - - [Operation](#operation) - - [Pre](#pre) - - [Post](#post) - - [Bin](#bin) - - [Parenthesis](#parenthesis) - - [Unary](#unary) - - [Cast](#cast) - - [Literal](#literal) - - [Boolean](#boolean) - - [String](#string) - - [Number](#number) - - [Inline](#inline) - - [Magic](#magic) - - [Nowdoc](#nowdoc) - - [Encapsed](#encapsed) - - [Statement](#statement) - - [Eval](#eval) - - [Exit](#exit) - - [Halt](#halt) - - [Clone](#clone) - - [Declare](#declare) - - [Global](#global) - - [Static](#static) - - [Include](#include) - - [Assign](#assign) - - [RetIf](#retif) - - [If](#if) - - [Do](#do) - - [While](#while) - - [For](#for) - - [Foreach](#foreach) - - [Switch](#switch) - - [Goto](#goto) - - [Silent](#silent) - - [Try](#try) - - [Catch](#catch) - - [Throw](#throw) - - [Call](#call) - - [Closure](#closure) - - [New](#new) - - [UseGroup](#usegroup) - - [UseItem](#useitem) - - [Block](#block) - - [Program](#program) - - [Namespace](#namespace) - - [Sys](#sys) - - [Echo](#echo) - - [List](#list) - - [Print](#print) - - [Isset](#isset) - - [Unset](#unset) - - [Empty](#empty) - - [Declaration](#declaration) - - [Class](#class) - - [Interface](#interface) - - [Trait](#trait) - - [Constant](#constant) - - [ClassConstant](#classconstant) - - [Function](#function) - - [Method](#method) - - [Parameter](#parameter) - - [Property](#property) - -* * * - -**Parameters** - -- `withPositions` -- `withSource` - -### resolvePrecedence - -Check and fix precence, by default using right - -**Parameters** - -- `result` - -### prepare - -Prepares an AST node - -**Parameters** - -- `kind` **([String](#string) | null)** Defines the node type - (if null, the kind must be passed at the function call) -- `parser` **Parser** The parser instance (use for extracting locations) - -Returns **[Function](#function)** - -## AST - -The AST builder class - -**Parameters** - -- `withPositions` -- `withSource` - -**Properties** - -- `withPositions` **[Boolean](#boolean)** Should locate any node (by default false) -- `withSource` **[Boolean](#boolean)** Should extract the node original code (by default false) - -### resolvePrecedence - -Check and fix precence, by default using right - -**Parameters** - -- `result` - -### prepare - -Prepares an AST node - -**Parameters** - -- `kind` **([String](#string) | null)** Defines the node type - (if null, the kind must be passed at the function call) -- `parser` **Parser** The parser instance (use for extracting locations) - -Returns **[Function](#function)** - -## Array - -**Extends Expression** - -Defines an array structure - -**Properties** - -- `items` **[Array](#array)<[Entry](#entry)>** List of array items -- `shortForm` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Indicate if the short array syntax is used, ex `[]` instead `array()` - -**Examples** - -```javascript -// PHP code : -[1, 'foo' => 'bar', 3] - -// AST structure : -{ - "kind": "array", - "shortForm": true - "items": [{ - "kind": "entry", - "key": null, - "value": {"kind": "number", "value": "1"} - }, { - "kind": "entry", - "key": {"kind": "string", "value": "foo", "isDoubleQuote": false}, - "value": {"kind": "string", "value": "bar", "isDoubleQuote": false} - }, { - "kind": "entry", - "key": null, - "value": {"kind": "number", "value": "3"} - }] -} -``` - -## Assign - -**Extends Statement** - -Assigns a value to the specified target - -**Properties** - -- `left` **[Expression](#expression)** -- `right` **[Expression](#expression)** -- `operator` **[String](#string)** - -## Bin - -**Extends Operation** - -Binary operations - -**Properties** - -- `type` **[String](#string)** -- `left` **[Expression](#expression)** -- `right` **[Expression](#expression)** - -## Block - -**Extends Statement** - -A block statement, i.e., a sequence of statements surrounded by braces. - -**Properties** - -- `children` **[Array](#array)<[Node](#node)>** - -## Boolean - -**Extends Literal** - -Defines a boolean value (true/false) - -## Break - -**Extends Node** - -A break statement - -**Properties** - -- `level` **([Number](#number) \| [Null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null))** - -## Call - -**Extends Statement** - -Executes a call statement - -**Properties** - -- `arguments` **[Array](#array)<Arguments>** - -## Case - -**Extends Node** - -A switch case statement - -**Properties** - -- `test` **([Expression](#expression) | null)** if null, means that the default case -- `body` **([Block](#block) | null)** - -## Cast - -**Extends Operation** - -Binary operations - -**Properties** - -- `type` **[String](#string)** -- `what` **[Expression](#expression)** - -## Catch - -**Extends Statement** - -Defines a catch statement - -**Properties** - -- `what` **[Array](#array)<[Identifier](#identifier)>** -- `variable` **[Variable](#variable)** -- `body` **[Statement](#statement)** - -## Class - -**Extends Declaration** - -A class definition - -**Properties** - -- `extends` **([Identifier](#identifier) | null)** -- `implements` **[Array](#array)<[Identifier](#identifier)>** -- `body` **[Array](#array)<[Declaration](#declaration)>** -- `isAnonymous` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `isAbstract` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `isFinal` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** - -## ClassConstant - -**Extends Constant** - -Defines a class/interface/trait constant - -**Properties** - -- `isStatic` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `visibility` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** - -## Clone - -**Extends Statement** - -Defines a clone call - -**Properties** - -- `what` **[Expression](#expression)** - -## Closure - -**Extends Statement** - -Defines a closure - -**Properties** - -- `arguments` **[Array](#array)<[Parameter](#parameter)>** -- `uses` **[Array](#array)<[Variable](#variable)>** -- `type` **[Identifier](#identifier)** -- `byref` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `nullable` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `body` **([Block](#block) | null)** -- `isStatic` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** - -## Constant - -**Extends Declaration** - -Defines a namespace constant - -**Properties** - -- `value` **([Node](#node) | null)** - -## ConstRef - -**Extends Expression** - -A constant reference - -**Properties** - -- `name` **([String](#string) \| [Node](#node))** - -## Continue - -**Extends Node** - -A continue statement - -**Properties** - -- `level` **([Number](#number) \| [Null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null))** - -## Declaration - -**Extends Statement** - -A declaration statement (function, class, interface...) - -**Properties** - -- `name` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** - -### parseFlags - -Generic flags parser - -**Parameters** - -- `flags` **[Array](#array)<Integer>** - -Returns **void** - -## Declare - -**Extends Block** - -The declare construct is used to set execution directives for a block of code - -**Properties** - -- `what` **[Array](#array)<[Expression](#expression)>** -- `mode` **[String](#string)** - -### MODE_SHORT - -The node is declared as a short tag syntax : - -```php -** - -## Echo - -**Extends Sys** - -Defines system based call - -## Empty - -**Extends Sys** - -Defines an empty check call - -## Encapsed - -**Extends Literal** - -Defines an encapsed string (contains expressions) - -**Properties** - -- `type` **[String](#string)** Defines the type of encapsed string (shell, heredoc, string) -- `label` **([String](#string) \| [Null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null))** The heredoc label, defined only when the type is heredoc - -### TYPE_STRING - -The node is a double quote string : - -```php -bar_$baz; -``` - -Type: [String](#string) - -## Entry - -**Extends Node** - -An array entry - see [Array](#array) - -**Properties** - -- `key` **([Node](#node) | null)** The entry key/offset -- `value` **[Node](#node)** The entry value - -## Error - -**Extends Node** - -Defines an error node (used only on silentMode) - -**Properties** - -- `message` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** -- `line` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** -- `token` **([number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) \| [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** -- `expected` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array))** - -## Eval - -**Extends Statement** - -Defines an eval statement - -**Properties** - -- `source` **[Node](#node)** - -## Exit - -**Extends Statement** - -Defines an exit / die call - -**Properties** - -- `status` **([Node](#node) | null)** - -## Expression - -**Extends Node** - -Any expression node. Since the left-hand side of an assignment may -be any expression in general, an expression can also be a pattern. - -## For - -**Extends Statement** - -Defines a for iterator - -**Properties** - -- `init` **[Array](#array)<[Expression](#expression)>** -- `test` **[Array](#array)<[Expression](#expression)>** -- `increment` **[Array](#array)<[Expression](#expression)>** -- `body` **[Statement](#statement)** -- `shortForm` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** - -## Foreach - -**Extends Statement** - -Defines a foreach iterator - -**Properties** - -- `source` **[Expression](#expression)** -- `key` **([Expression](#expression) | null)** -- `value` **[Expression](#expression)** -- `body` **[Statement](#statement)** -- `shortForm` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** - -## Function - -**Extends Declaration** - -Defines a classic function - -**Properties** - -- `arguments` **[Array](#array)<[Parameter](#parameter)>** -- `type` **[Identifier](#identifier)** -- `byref` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `nullable` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `body` **([Block](#block) | null)** - -## Global - -**Extends Statement** - -Imports a variable from the global scope - -**Properties** - -- `items` **[Array](#array)<[Variable](#variable)>** - -## Goto - -**Extends Statement** - -Defines goto statement - -**Properties** - -- `label` **[String](#string)** - -## Halt - -**Extends Statement** - -Halts the compiler execution - -**Properties** - -- `after` **[String](#string)** String after the halt statement - -## Identifier - -**Extends Node** - -Defines an identifier node - -**Properties** - -- `name` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** -- `resolution` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** - -### UNQUALIFIED_NAME - -This is an identifier without a namespace separator, such as Foo - -Type: [String](#string) - -### QUALIFIED_NAME - -This is an identifier with a namespace separator, such as Foo\\Bar - -Type: [String](#string) - -### FULL_QUALIFIED_NAME - -This is an identifier with a namespace separator that begins with -a namespace separator, such as \\Foo\\Bar. The namespace \\Foo is also -a fully qualified name. - -Type: [String](#string) - -### RELATIVE_NAME - -This is an identifier starting with namespace, such as namespace\\Foo\\Bar. - -Type: [String](#string) - -## If - -**Extends Statement** - -Defines a if statement - -**Properties** - -- `test` **[Expression](#expression)** -- `body` **[Block](#block)** -- `alternate` **([Block](#block) \| [If](#if) | null)** -- `shortForm` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** - -## Include - -**Extends Statement** - -Defines system include call - -**Properties** - -- `target` **[Node](#node)** -- `once` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `require` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** - -## Inline - -**Extends Literal** - -Defines inline html output (treated as echo output) - -## Interface - -**Extends Declaration** - -An interface definition - -**Properties** - -- `extends` **[Array](#array)<[Identifier](#identifier)>** -- `body` **[Array](#array)<[Declaration](#declaration)>** - -## Isset - -**Extends Sys** - -Defines an isset call - -## Label - -**Extends Node** - -A label statement (referenced by goto) - -**Properties** - -- `name` **[String](#string)** - -## List - -**Extends Sys** - -Defines list assignment - -## Literal - -**Extends Expression** - -Defines an array structure - -**Properties** - -- `value` **([Node](#node) \| [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) \| [boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) | null)** - -## Location - -Defines the location of the node (with it's source contents as string) - -**Parameters** - -- `source` -- `start` -- `end` - -**Properties** - -- `source` **([String](#string) | null)** -- `start` **[Position](#position)** -- `end` **[Position](#position)** - -## Lookup - -**Extends Expression** - -Lookup on an offset in the specified object - -**Properties** - -- `what` **[Expression](#expression)** -- `offset` **[Expression](#expression)** - -## Magic - -**Extends Literal** - -Defines magic constant - -## Method - -**Extends Function** - -Defines a class/interface/trait method - -**Properties** - -- `isAbstract` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `isFinal` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `isStatic` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `visibility` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** - -## Namespace - -**Extends Block** - -The main program node - -**Properties** - -- `name` **[String](#string)** -- `withBrackets` **[Boolean](#boolean)** - -## New - -**Extends Statement** - -Creates a new instance of the specified class - -**Properties** - -- `what` **([Identifier](#identifier) \| [Variable](#variable) \| [Class](#class))** -- `arguments` **[Array](#array)<Arguments>** - -## Node - -A generic AST node - -**Parameters** - -- `kind` -- `location` - -**Properties** - -- `loc` **([Location](#location) | null)** -- `kind` **[String](#string)** - -### extends - -Helper for extending the Node class - -**Parameters** - -- `constructor` **[Function](#function)** - -Returns **[Function](#function)** - -## String - -**Extends Literal** - -Defines a nowdoc string - -**Properties** - -- `label` **[String](#string)** - -## String - -**Extends Literal** - -Defines a string (simple ou double quoted) - chars are already escaped - -**Properties** - -- `isDoubleQuote` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** - -## Number - -**Extends Literal** - -Defines a numeric value - -## OffsetLookup - -**Extends Lookup** - -Lookup on an offset in an array - -## Operation - -**Extends Expression** - -Defines binary operations - -## Parameter - -**Extends Declaration** - -Defines a function parameter - -**Properties** - -- `type` **([Identifier](#identifier) | null)** -- `value` **([Node](#node) | null)** -- `byref` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `variadic` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `nullable` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** - -## Parenthesis - -**Extends Operation** - -Parenthesis encapsulation `(... expr ...)` - -**Properties** - -- `inner` **[Expression](#expression)** - -## Position - -Each Position object consists of a line number (1-indexed) and a column number (0-indexed): - -**Parameters** - -- `line` -- `column` -- `offset` - -**Properties** - -- `line` **[Number](#number)** -- `column` **[Number](#number)** -- `offset` **[Number](#number)** - -## Post - -**Extends Operation** - -Defines a post operation `$i++` or `$i--` - -**Properties** - -- `type` **[String](#string)** -- `what` **[Variable](#variable)** - -## Pre - -**Extends Operation** - -Defines a pre operation `++$i` or `--$i` - -**Properties** - -- `type` **[String](#string)** -- `what` **[Variable](#variable)** - -## Print - -**Extends Sys** - -Outputs - -## Program - -**Extends Block** - -The main program node - -**Properties** - -- `errors` **[Array](#array)<[Error](#error)>** - -## Property - -**Extends Declaration** - -Defines a class property - -**Properties** - -- `isFinal` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `isStatic` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** -- `visibility` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** -- `value` **([Node](#node) | null)** - -## PropertyLookup - -**Extends Lookup** - -Lookup to an object property - -## RetIf - -**Extends Statement** - -Defines a short if statement that returns a value - -**Properties** - -- `test` **[Expression](#expression)** -- `trueExpr` **[Expression](#expression)** -- `falseExpr` **[Expression](#expression)** - -## Return - -**Extends Node** - -A continue statement - -**Properties** - -- `expr` **([Expression](#expression) | null)** - -## Silent - -**Extends Statement** - -Avoids to show/log warnings & notices from the inner expression - -**Properties** - -- `expr` **[Expression](#expression)** - -## Statement - -**Extends Node** - -Any statement. - -## Static - -**Extends Statement** - -Declares a static variable into the current scope - -**Properties** - -- `items` **([Array](#array)<[Variable](#variable)> | [Array](#array)<[Assign](#assign)>)** - -## StaticLookup - -**Extends Lookup** - -Lookup to a static property - -## Switch - -**Extends Statement** - -Defines a switch statement - -**Properties** - -- `test` **[Expression](#expression)** -- `body` **[Block](#block)** -- `shortForm` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** - -## Sys - -**Extends Statement** - -Defines system based call - -**Properties** - -- `arguments` **[Array](#array)<[Node](#node)>** - -## Throw - -**Extends Statement** - -Defines a throw statement - -**Properties** - -- `what` **[Expression](#expression)** - -## Trait - -**Extends Declaration** - -A trait definition - -**Properties** - -- `extends` **([Identifier](#identifier) | null)** -- `implements` **[Array](#array)<[Identifier](#identifier)>** -- `body` **[Array](#array)<[Declaration](#declaration)>** - -## TraitAlias - -**Extends Node** - -Defines a trait alias - -**Properties** - -- `trait` **([Identifier](#identifier) | null)** -- `method` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** -- `as` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) | null)** -- `visibility` **([string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) | null)** - -## TraitPrecedence - -**Extends Node** - -Defines a trait alias - -**Properties** - -- `trait` **([Identifier](#identifier) | null)** -- `method` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** -- `instead` **[Array](#array)<[Identifier](#identifier)>** - -## TraitUse - -**Extends Node** - -Defines a trait usage - -**Properties** - -- `traits` **[Array](#array)<[Identifier](#identifier)>** -- `adaptations` **([Array](#array)<[Node](#node)> | null)** - -## Try - -**Extends Statement** - -Defines a try statement - -**Properties** - -- `body` **[Block](#block)** -- `catches` **[Array](#array)<[Catch](#catch)>** -- `allways` **[Block](#block)** - -## Unary - -**Extends Operation** - -Unary operations - -**Properties** - -- `type` **[String](#string)** -- `what` **[Expression](#expression)** - -## Unset - -**Extends Sys** - -Deletes references to a list of variables - -## UseGroup - -**Extends Statement** - -Defines a use statement (with a list of use items) - -**Properties** - -- `name` **([String](#string) | null)** -- `type` **([String](#string) | null)** Possible value : function, const -- `item` **[Array](#array)<[UseItem](#useitem)>** - -## UseItem - -**Extends Statement** - -Defines a use statement (from namespace) - -**Properties** - -- `name` **[String](#string)** -- `type` **([String](#string) | null)** Possible value : function, const -- `alias` **([String](#string) | null)** - -### TYPE_CONST - -Importing a constant - -Type: [String](#string) - -### TYPE_FUNC - -Importing a function - -Type: [String](#string) - -## Variable - -**Extends Expression** - -Any expression node. Since the left-hand side of an assignment may -be any expression in general, an expression can also be a pattern. - -**Properties** - -- `name` **([String](#string) \| [Node](#node))** The variable name (can be a complex expression when the name is resolved dynamically) -- `byref` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Indicate if the variable reference is used, ex `&$foo` -- `curly` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** Indicate if the name is defined between curlies, ex `${foo}` - -**Examples** - -```javascript -// PHP code : -&$foo -// AST output -{ - "kind": "variable", - "name": "foo", - "byref": true, - "curly": false -} -``` - -## Variadic - -**Extends Expression** - -Introduce a list of items into the arguments of the call - -**Properties** - -- `what` **([Array](#array) \| [Expression](#expression))** - -## While - -**Extends Statement** - -Defines a while statement - -**Properties** - -- `test` **[Expression](#expression)** -- `body` **[Statement](#statement)** -- `shortForm` **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** - -## Yield - -**Extends Expression** - -Defines a yield generator statement - -**Properties** - -- `value` **([Expression](#expression) \| [Null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null))** -- `key` **([Expression](#expression) \| [Null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null))** - -## YieldFrom - -**Extends Expression** - -Defines a yield from generator statement - -**Properties** - -- `value` **[Expression](#expression)** diff --git a/docs/Array.html b/docs/Array.html new file mode 100644 index 000000000..2da285a0e --- /dev/null +++ b/docs/Array.html @@ -0,0 +1,816 @@ + + + + + + + + + Array - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Array +

+ + + + +
+
+ +

+ + Array + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Array() +

+
+ + + + + +
+

Defines an array structure

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
items + + + + Entry + + + | + + + Expr + + + | + + + Variable + + + + + + + +

List of array items

+
shortForm + + + + boolean + + + + + + + +

Indicate if the short array syntax is used, ex [] instead array()

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + +
+ + + + + +
Example
+ + +
// PHP code :
+[1, 'foo' => 'bar', 3]
+
+// AST structure :
+{
+ "kind": "array",
+ "shortForm": true
+ "items": [
+   {"kind": "number", "value": "1"},
+   {
+     "kind": "entry",
+     "key": {"kind": "string", "value": "foo", "isDoubleQuote": false},
+     "value": {"kind": "string", "value": "bar", "isDoubleQuote": false}
+   },
+   {"kind": "number", "value": "3"}
+ ]
+}
+ + +
+ + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Assign.html b/docs/Assign.html new file mode 100644 index 000000000..0a65eac22 --- /dev/null +++ b/docs/Assign.html @@ -0,0 +1,803 @@ + + + + + + + + + Assign - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Assign +

+ + + + +
+
+ +

+ + Assign + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Assign() +

+
+ + + + + +
+

Assigns a value to the specified target

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
left + + + + Expression + + + + + + + + +
right + + + + Expression + + + + + + + + +
operator + + + + String + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Bin.html b/docs/Bin.html new file mode 100644 index 000000000..70c31082a --- /dev/null +++ b/docs/Bin.html @@ -0,0 +1,803 @@ + + + + + + + + + Bin - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Bin +

+ + + + +
+
+ +

+ + Bin + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Bin() +

+
+ + + + + +
+

Binary operations

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
type + + + + String + + + + + + + + +
left + + + + Expression + + + + + + + + +
right + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Block.html b/docs/Block.html new file mode 100644 index 000000000..ce990441a --- /dev/null +++ b/docs/Block.html @@ -0,0 +1,745 @@ + + + + + + + + + Block - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Block +

+ + + + +
+
+ +

+ + Block + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Block() +

+
+ + + + + +
+

A block statement, i.e., a sequence of statements surrounded by braces.

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
children + + + + Array.<Node> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Boolean.html b/docs/Boolean.html new file mode 100644 index 000000000..260130632 --- /dev/null +++ b/docs/Boolean.html @@ -0,0 +1,687 @@ + + + + + + + + + Boolean - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Boolean +

+ + + + +
+
+ +

+ + Boolean + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Boolean() +

+
+ + + + + +
+

Defines a boolean value (true/false)

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Break.html b/docs/Break.html new file mode 100644 index 000000000..58e98c2ad --- /dev/null +++ b/docs/Break.html @@ -0,0 +1,751 @@ + + + + + + + + + Break - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Break +

+ + + + +
+
+ +

+ + Break + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Break() +

+
+ + + + + +
+

A break statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
level + + + + Number + + + | + + + Null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Call.html b/docs/Call.html new file mode 100644 index 000000000..49e2277b4 --- /dev/null +++ b/docs/Call.html @@ -0,0 +1,786 @@ + + + + + + + + + Call - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Call +

+ + + + +
+
+ +

+ + Call + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Call() +

+
+ + + + + +
+

Executes a call statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
what + + + + Identifier + + + | + + + Variable + + + | + + + ? + + + + + + + + +
arguments + + + + Array.<Arguments> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Case.html b/docs/Case.html new file mode 100644 index 000000000..7f5ee4e7a --- /dev/null +++ b/docs/Case.html @@ -0,0 +1,786 @@ + + + + + + + + + Case - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Case +

+ + + + +
+
+ +

+ + Case + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Case() +

+
+ + + + + +
+

A switch case statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
test + + + + Expression + + + | + + + null + + + + + + + +

if null, means that the default case

+
body + + + + Block + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Cast.html b/docs/Cast.html new file mode 100644 index 000000000..13a42c1ed --- /dev/null +++ b/docs/Cast.html @@ -0,0 +1,803 @@ + + + + + + + + + Cast - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Cast +

+ + + + +
+
+ +

+ + Cast + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Cast() +

+
+ + + + + +
+

Binary operations

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
type + + + + String + + + + + + + + +
raw + + + + String + + + + + + + + +
what + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Catch.html b/docs/Catch.html new file mode 100644 index 000000000..ef443b27b --- /dev/null +++ b/docs/Catch.html @@ -0,0 +1,814 @@ + + + + + + + + + Catch - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Catch +

+ + + + +
+
+ +

+ + Catch + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Catch() +

+
+ + + + + +
+

Defines a catch statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
what + + + + Array.<Identifier> + + + + + + + + +
variable + + + + Variable + + + + + + + + +
body + + + + Statement + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Class.html b/docs/Class.html new file mode 100644 index 000000000..715c17f67 --- /dev/null +++ b/docs/Class.html @@ -0,0 +1,1051 @@ + + + + + + + + + Class - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Class +

+ + + + +
+
+ +

+ + Class + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Class() +

+
+ + + + + +
+

A class definition

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
extends + + + + Identifier + + + | + + + null + + + + + + + + +
implements + + + + Array.<Identifier> + + + + + + + + +
body + + + + Array.<Declaration> + + + + + + + + +
isAnonymous + + + + boolean + + + + + + + + +
isAbstract + + + + boolean + + + + + + + + +
isFinal + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ parseFlags(flags) → {void} +

+
+ + + + + +
+

Generic flags parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
flags + + + + Array.<Integer> + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/ClassConstant.html b/docs/ClassConstant.html new file mode 100644 index 000000000..2e71f5a8d --- /dev/null +++ b/docs/ClassConstant.html @@ -0,0 +1,891 @@ + + + + + + + + + ClassConstant - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ClassConstant +

+ + + + +
+
+ +

+ + ClassConstant + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new ClassConstant() +

+
+ + + + + +
+

Defines a class/interface/trait constant

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
visibility + + + + string + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ parseFlags(flags) → {void} +

+
+ + + + + +
+

Generic flags parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
flags + + + + Array.<Integer> + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/ClassReference.html b/docs/ClassReference.html new file mode 100644 index 000000000..2c14ce119 --- /dev/null +++ b/docs/ClassReference.html @@ -0,0 +1,774 @@ + + + + + + + + + ClassReference - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ClassReference +

+ + + + +
+
+ +

+ + ClassReference + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new ClassReference() +

+
+ + + + + +
+

Defines a class reference node

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + string + + + + + + + + +
resolution + + + + string + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Clone.html b/docs/Clone.html new file mode 100644 index 000000000..d1e47ed46 --- /dev/null +++ b/docs/Clone.html @@ -0,0 +1,745 @@ + + + + + + + + + Clone - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Clone +

+ + + + +
+
+ +

+ + Clone + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Clone() +

+
+ + + + + +
+

Defines a clone call

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
what + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Closure.html b/docs/Closure.html new file mode 100644 index 000000000..7d8a2589d --- /dev/null +++ b/docs/Closure.html @@ -0,0 +1,925 @@ + + + + + + + + + Closure - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Closure +

+ + + + +
+
+ +

+ + Closure + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Closure() +

+
+ + + + + +
+

Defines a closure

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
arguments + + + + Array.<Parameter> + + + + + + + + +
uses + + + + Array.<Variable> + + + + + + + + +
type + + + + Identifier + + + + + + + + +
byref + + + + boolean + + + + + + + + +
nullable + + + + boolean + + + + + + + + +
body + + + + Block + + + | + + + null + + + + + + + + +
isStatic + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Comment.html b/docs/Comment.html new file mode 100644 index 000000000..ffc7148c4 --- /dev/null +++ b/docs/Comment.html @@ -0,0 +1,745 @@ + + + + + + + + + Comment - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Comment +

+ + + + +
+
+ +

+ + Comment + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Comment() +

+
+ + + + + +
+

Abstract documentation node (ComentLine or CommentBlock)

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + + + String + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/CommentBlock.html b/docs/CommentBlock.html new file mode 100644 index 000000000..c04b150f2 --- /dev/null +++ b/docs/CommentBlock.html @@ -0,0 +1,687 @@ + + + + + + + + + CommentBlock - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ CommentBlock +

+ + + + +
+
+ +

+ + CommentBlock + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new CommentBlock() +

+
+ + + + + +
+

A comment block (multiline)

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/CommentLine.html b/docs/CommentLine.html new file mode 100644 index 000000000..6910e7416 --- /dev/null +++ b/docs/CommentLine.html @@ -0,0 +1,687 @@ + + + + + + + + + CommentLine - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ CommentLine +

+ + + + +
+
+ +

+ + CommentLine + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new CommentLine() +

+
+ + + + + +
+

A single line comment

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/ConstRef.html b/docs/ConstRef.html new file mode 100644 index 000000000..7ee36795b --- /dev/null +++ b/docs/ConstRef.html @@ -0,0 +1,648 @@ + + + + + + + + + ConstRef - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ConstRef +

+ + + + +
+
+ +

+ + ConstRef + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new ConstRef() +

+
+ + + + + +
+

A constant reference

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + String + + + | + + + Node + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Constant.html b/docs/Constant.html new file mode 100644 index 000000000..c68a94821 --- /dev/null +++ b/docs/Constant.html @@ -0,0 +1,798 @@ + + + + + + + + + Constant - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Constant +

+ + + + +
+
+ +

+ + Constant + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Constant() +

+
+ + + + + +
+

Defines a constant

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + string + + + + + + + + +
value + + + + Node + + + | + + + string + + + | + + + number + + + | + + + boolean + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/ConstantStatement.html b/docs/ConstantStatement.html new file mode 100644 index 000000000..8aa743828 --- /dev/null +++ b/docs/ConstantStatement.html @@ -0,0 +1,745 @@ + + + + + + + + + ConstantStatement - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ConstantStatement +

+ + + + +
+
+ +

+ + ConstantStatement + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new ConstantStatement() +

+
+ + + + + +
+

Declares a constants into the current scope

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
constants + + + + Array.<Constant> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Continue.html b/docs/Continue.html new file mode 100644 index 000000000..ffedfd54a --- /dev/null +++ b/docs/Continue.html @@ -0,0 +1,751 @@ + + + + + + + + + Continue - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Continue +

+ + + + +
+
+ +

+ + Continue + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Continue() +

+
+ + + + + +
+

A continue statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
level + + + + Number + + + | + + + Null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Declaration.html b/docs/Declaration.html new file mode 100644 index 000000000..5903eb71d --- /dev/null +++ b/docs/Declaration.html @@ -0,0 +1,897 @@ + + + + + + + + + Declaration - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Declaration +

+ + + + +
+
+ +

+ + Declaration + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Declaration() +

+
+ + + + + +
+

A declaration statement (function, class, interface...)

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + Identifier + + + | + + + string + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ parseFlags(flags) → {void} +

+
+ + + + + +
+

Generic flags parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
flags + + + + Array.<Integer> + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Declare.html b/docs/Declare.html new file mode 100644 index 000000000..f85838c7a --- /dev/null +++ b/docs/Declare.html @@ -0,0 +1,785 @@ + + + + + + + + + Declare - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Declare +

+ + + + +
+
+ +

+ + Declare + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Declare() +

+
+ + + + + +
+

The declare construct is used to set execution directives for a block of code

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
directives + + + + Array.<Array> + + + + + + + + +
mode + + + + String + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/DeclareDirective.html b/docs/DeclareDirective.html new file mode 100644 index 000000000..cf92674e2 --- /dev/null +++ b/docs/DeclareDirective.html @@ -0,0 +1,798 @@ + + + + + + + + + DeclareDirective - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ DeclareDirective +

+ + + + +
+
+ +

+ + DeclareDirective + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new DeclareDirective() +

+
+ + + + + +
+

Defines a constant

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + Identifier + + + + + + + + +
value + + + + Node + + + | + + + string + + + | + + + number + + + | + + + boolean + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Do.html b/docs/Do.html new file mode 100644 index 000000000..bb0f4fae7 --- /dev/null +++ b/docs/Do.html @@ -0,0 +1,774 @@ + + + + + + + + + Do - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Do +

+ + + + +
+
+ +

+ + Do + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Do() +

+
+ + + + + +
+

Defines a do/while statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
test + + + + Expression + + + + + + + + +
body + + + + Statement + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Echo.html b/docs/Echo.html new file mode 100644 index 000000000..c57b547c3 --- /dev/null +++ b/docs/Echo.html @@ -0,0 +1,745 @@ + + + + + + + + + Echo - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Echo +

+ + + + +
+
+ +

+ + Echo + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Echo() +

+
+ + + + + +
+

Defines system based call

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
shortForm + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Empty.html b/docs/Empty.html new file mode 100644 index 000000000..2bcecd6cf --- /dev/null +++ b/docs/Empty.html @@ -0,0 +1,687 @@ + + + + + + + + + Empty - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Empty +

+ + + + +
+
+ +

+ + Empty + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Empty() +

+
+ + + + + +
+

Defines an empty check call

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Encapsed.html b/docs/Encapsed.html new file mode 100644 index 000000000..dc183fb92 --- /dev/null +++ b/docs/Encapsed.html @@ -0,0 +1,780 @@ + + + + + + + + + Encapsed - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Encapsed +

+ + + + +
+
+ +

+ + Encapsed + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Encapsed() +

+
+ + + + + +
+

Defines an encapsed string (contains expressions)

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
type + + + + String + + + + + + + +

Defines the type of encapsed string (shell, heredoc, string)

+
label + + + + String + + + | + + + Null + + + + + + + +

The heredoc label, defined only when the type is heredoc

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/EncapsedPart.html b/docs/EncapsedPart.html new file mode 100644 index 000000000..cc81d9ae5 --- /dev/null +++ b/docs/EncapsedPart.html @@ -0,0 +1,745 @@ + + + + + + + + + EncapsedPart - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ EncapsedPart +

+ + + + +
+
+ +

+ + EncapsedPart + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new EncapsedPart() +

+
+ + + + + +
+

Part of Encapsed node

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
what + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Entry.html b/docs/Entry.html new file mode 100644 index 000000000..eb1ac24d7 --- /dev/null +++ b/docs/Entry.html @@ -0,0 +1,780 @@ + + + + + + + + + Entry - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Entry +

+ + + + +
+
+ +

+ + Entry + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Entry() +

+
+ + + + + +
+

An array entry - see Array

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
key + + + + Node + + + | + + + null + + + + + + + +

The entry key/offset

+
value + + + + Node + + + + + + + +

The entry value

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Error.html b/docs/Error.html new file mode 100644 index 000000000..ba158017a --- /dev/null +++ b/docs/Error.html @@ -0,0 +1,844 @@ + + + + + + + + + Error - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Error +

+ + + + +
+
+ +

+ + Error + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Error() +

+
+ + + + + +
+

Defines an error node (used only on silentMode)

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
message + + + + string + + + + + + + + +
line + + + + number + + + + + + + + +
token + + + + number + + + | + + + string + + + + + + + + +
expected + + + + string + + + | + + + array + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Eval.html b/docs/Eval.html new file mode 100644 index 000000000..19e54792d --- /dev/null +++ b/docs/Eval.html @@ -0,0 +1,745 @@ + + + + + + + + + Eval - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Eval +

+ + + + +
+
+ +

+ + Eval + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Eval() +

+
+ + + + + +
+

Defines an eval statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
source + + + + Node + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Exit.html b/docs/Exit.html new file mode 100644 index 000000000..6fa060802 --- /dev/null +++ b/docs/Exit.html @@ -0,0 +1,780 @@ + + + + + + + + + Exit - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Exit +

+ + + + +
+
+ +

+ + Exit + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Exit() +

+
+ + + + + +
+

Defines an exit / die call

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
status + + + + Node + + + | + + + null + + + + + + + + +
useDie + + + + Boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Expression.html b/docs/Expression.html new file mode 100644 index 000000000..6e1300cc9 --- /dev/null +++ b/docs/Expression.html @@ -0,0 +1,688 @@ + + + + + + + + + Expression - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Expression +

+ + + + +
+
+ +

+ + Expression + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Expression() +

+
+ + + + + +
+

Any expression node. Since the left-hand side of an assignment may +be any expression in general, an expression can also be a pattern.

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/ExpressionStatement.html b/docs/ExpressionStatement.html new file mode 100644 index 000000000..e3e272290 --- /dev/null +++ b/docs/ExpressionStatement.html @@ -0,0 +1,745 @@ + + + + + + + + + ExpressionStatement - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ExpressionStatement +

+ + + + +
+
+ +

+ + ExpressionStatement + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new ExpressionStatement() +

+
+ + + + + +
+

Defines an expression based statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
expression + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/For.html b/docs/For.html new file mode 100644 index 000000000..4ee611899 --- /dev/null +++ b/docs/For.html @@ -0,0 +1,872 @@ + + + + + + + + + For - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ For +

+ + + + +
+
+ +

+ + For + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new For() +

+
+ + + + + +
+

Defines a for iterator

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
init + + + + Array.<Expression> + + + + + + + + +
test + + + + Array.<Expression> + + + + + + + + +
increment + + + + Array.<Expression> + + + + + + + + +
body + + + + Statement + + + + + + + + +
shortForm + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Foreach.html b/docs/Foreach.html new file mode 100644 index 000000000..f27971669 --- /dev/null +++ b/docs/Foreach.html @@ -0,0 +1,878 @@ + + + + + + + + + Foreach - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Foreach +

+ + + + +
+
+ +

+ + Foreach + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Foreach() +

+
+ + + + + +
+

Defines a foreach iterator

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
source + + + + Expression + + + + + + + + +
key + + + + Expression + + + | + + + null + + + + + + + + +
value + + + + Expression + + + + + + + + +
body + + + + Statement + + + + + + + + +
shortForm + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Function.html b/docs/Function.html new file mode 100644 index 000000000..72013b75f --- /dev/null +++ b/docs/Function.html @@ -0,0 +1,1022 @@ + + + + + + + + + Function - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Function +

+ + + + +
+
+ +

+ + Function + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Function() +

+
+ + + + + +
+

Defines a classic function

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
arguments + + + + Array.<Parameter> + + + + + + + + +
type + + + + Identifier + + + + + + + + +
byref + + + + boolean + + + + + + + + +
nullable + + + + boolean + + + + + + + + +
body + + + + Block + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ parseFlags(flags) → {void} +

+
+ + + + + +
+

Generic flags parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
flags + + + + Array.<Integer> + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Global_.html b/docs/Global_.html new file mode 100644 index 000000000..cd410be56 --- /dev/null +++ b/docs/Global_.html @@ -0,0 +1,745 @@ + + + + + + + + + Global - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Global +

+ + + + +
+
+ +

+ + Global + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Global() +

+
+ + + + + +
+

Imports a variable from the global scope

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
items + + + + Array.<Variable> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Goto.html b/docs/Goto.html new file mode 100644 index 000000000..aa318e641 --- /dev/null +++ b/docs/Goto.html @@ -0,0 +1,756 @@ + + + + + + + + + Goto - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Goto +

+ + + + +
+
+ +

+ + Goto + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Goto() +

+
+ + + + + +
+

Defines goto statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
label + + + + String + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Halt.html b/docs/Halt.html new file mode 100644 index 000000000..c18c706c6 --- /dev/null +++ b/docs/Halt.html @@ -0,0 +1,756 @@ + + + + + + + + + Halt - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Halt +

+ + + + +
+
+ +

+ + Halt + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Halt() +

+
+ + + + + +
+

Halts the compiler execution

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
after + + + + String + + + + + + + +

String after the halt statement

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Identifier.html b/docs/Identifier.html new file mode 100644 index 000000000..a251a1124 --- /dev/null +++ b/docs/Identifier.html @@ -0,0 +1,745 @@ + + + + + + + + + Identifier - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Identifier +

+ + + + +
+
+ +

+ + Identifier + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Identifier() +

+
+ + + + + +
+

Defines an identifier node

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + string + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/If.html b/docs/If.html new file mode 100644 index 000000000..4d118728b --- /dev/null +++ b/docs/If.html @@ -0,0 +1,844 @@ + + + + + + + + + If - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ If +

+ + + + +
+
+ +

+ + If + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new If() +

+
+ + + + + +
+

Defines a if statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
test + + + + Expression + + + + + + + + +
body + + + + Block + + + + + + + + +
alternate + + + + Block + + + | + + + If + + + | + + + null + + + + + + + + +
shortForm + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Include.html b/docs/Include.html new file mode 100644 index 000000000..16f60850a --- /dev/null +++ b/docs/Include.html @@ -0,0 +1,803 @@ + + + + + + + + + Include - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Include +

+ + + + +
+
+ +

+ + Include + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Include() +

+
+ + + + + +
+

Defines system include call

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
target + + + + Node + + + + + + + + +
once + + + + boolean + + + + + + + + +
require + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Inline.html b/docs/Inline.html new file mode 100644 index 000000000..f64c5b4da --- /dev/null +++ b/docs/Inline.html @@ -0,0 +1,687 @@ + + + + + + + + + Inline - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Inline +

+ + + + +
+
+ +

+ + Inline + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Inline() +

+
+ + + + + +
+

Defines inline html output (treated as echo output)

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Interface.html b/docs/Interface.html new file mode 100644 index 000000000..b534b0c52 --- /dev/null +++ b/docs/Interface.html @@ -0,0 +1,929 @@ + + + + + + + + + Interface - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Interface +

+ + + + +
+
+ +

+ + Interface + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Interface() +

+
+ + + + + +
+

An interface definition

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
extends + + + + Array.<Identifier> + + + + + + + + +
body + + + + Array.<Declaration> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ parseFlags(flags) → {void} +

+
+ + + + + +
+

Generic flags parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
flags + + + + Array.<Integer> + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Isset.html b/docs/Isset.html new file mode 100644 index 000000000..2fa731e01 --- /dev/null +++ b/docs/Isset.html @@ -0,0 +1,687 @@ + + + + + + + + + Isset - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Isset +

+ + + + +
+
+ +

+ + Isset + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Isset() +

+
+ + + + + +
+

Defines an isset call

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Label.html b/docs/Label.html new file mode 100644 index 000000000..0d0296e36 --- /dev/null +++ b/docs/Label.html @@ -0,0 +1,745 @@ + + + + + + + + + Label - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Label +

+ + + + +
+
+ +

+ + Label + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Label() +

+
+ + + + + +
+

A label statement (referenced by goto)

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + String + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/List.html b/docs/List.html new file mode 100644 index 000000000..1cccec583 --- /dev/null +++ b/docs/List.html @@ -0,0 +1,745 @@ + + + + + + + + + List - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ List +

+ + + + +
+
+ +

+ + List + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new List() +

+
+ + + + + +
+

Defines list assignment

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
shortForm + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Literal.html b/docs/Literal.html new file mode 100644 index 000000000..24dfc1ee9 --- /dev/null +++ b/docs/Literal.html @@ -0,0 +1,798 @@ + + + + + + + + + Literal - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Literal +

+ + + + +
+
+ +

+ + Literal + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Literal() +

+
+ + + + + +
+

Defines an array structure

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
raw + + + + string + + + + + + + + +
value + + + + Node + + + | + + + string + + + | + + + number + + + | + + + boolean + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Location.html b/docs/Location.html new file mode 100644 index 000000000..be431f029 --- /dev/null +++ b/docs/Location.html @@ -0,0 +1,384 @@ + + + + + + + + + Location - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Location +

+ + + + +
+
+ +

+ + Location + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Location() +

+
+ + + + + +
+

Defines the location of the node (with it's source contents as string)

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
source + + + + String + + + | + + + null + + + + + + + + +
start + + + + Position + + + + + + + + +
end + + + + Position + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Lookup.html b/docs/Lookup.html new file mode 100644 index 000000000..0aa9d1e6e --- /dev/null +++ b/docs/Lookup.html @@ -0,0 +1,774 @@ + + + + + + + + + Lookup - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Lookup +

+ + + + +
+
+ +

+ + Lookup + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Lookup() +

+
+ + + + + +
+

Lookup on an offset in the specified object

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
what + + + + Expression + + + + + + + + +
offset + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Magic.html b/docs/Magic.html new file mode 100644 index 000000000..3e65f311d --- /dev/null +++ b/docs/Magic.html @@ -0,0 +1,687 @@ + + + + + + + + + Magic - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Magic +

+ + + + +
+
+ +

+ + Magic + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Magic() +

+
+ + + + + +
+

Defines magic constant

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Method.html b/docs/Method.html new file mode 100644 index 000000000..00ae84ada --- /dev/null +++ b/docs/Method.html @@ -0,0 +1,418 @@ + + + + + + + + + Method - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Method +

+ + + + +
+
+ +

+ + Method + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Method() +

+
+ + + + + +
+

Defines a class/interface/trait method

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
isAbstract + + + + boolean + + + + + + + + +
isFinal + + + + boolean + + + + + + + + +
isStatic + + + + boolean + + + + + + + + +
visibility + + + + string + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • _Function
  • +
+ + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Namespace.html b/docs/Namespace.html new file mode 100644 index 000000000..3564c1cee --- /dev/null +++ b/docs/Namespace.html @@ -0,0 +1,774 @@ + + + + + + + + + Namespace - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Namespace +

+ + + + +
+
+ +

+ + Namespace + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Namespace() +

+
+ + + + + +
+

The main program node

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + String + + + + + + + + +
withBrackets + + + + Boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/New.html b/docs/New.html new file mode 100644 index 000000000..f81f44a04 --- /dev/null +++ b/docs/New.html @@ -0,0 +1,786 @@ + + + + + + + + + New - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ New +

+ + + + +
+
+ +

+ + New + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new New() +

+
+ + + + + +
+

Creates a new instance of the specified class

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
what + + + + Identifier + + + | + + + Variable + + + | + + + Class + + + + + + + + +
arguments + + + + Array.<Arguments> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Node.html b/docs/Node.html new file mode 100644 index 000000000..a323a7978 --- /dev/null +++ b/docs/Node.html @@ -0,0 +1,1003 @@ + + + + + + + + + Node - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Node +

+ + + + +
+
+ +

+ + Node + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Node() +

+
+ + + + + +
+

A generic AST node

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
loc + + + + Location + + + | + + + null + + + + + + + + + + + + +
leadingComments + + + + Array.<Comment> + + + + + + + + + + + + +
trailingComments + + + + Array.<Comment> + + + + + + + + + + + <nullable>
+ +
+ +
kind + + + + String + + + + + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ (static) extends(type, constructor) → {function} +

+
+ + + + + +
+

Helper for extending the Node class

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
type + + + + String + + + + + + + + + +
constructor + + + + function + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Noop.html b/docs/Noop.html new file mode 100644 index 000000000..6cbd18c45 --- /dev/null +++ b/docs/Noop.html @@ -0,0 +1,688 @@ + + + + + + + + + Noop - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Noop +

+ + + + +
+
+ +

+ + Noop + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Noop() +

+
+ + + + + +
+

Ignore this node, it implies a no operation block, for example : +[$foo, $bar, /* here a noop node * /]

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/NowDoc.html b/docs/NowDoc.html new file mode 100644 index 000000000..d13637899 --- /dev/null +++ b/docs/NowDoc.html @@ -0,0 +1,803 @@ + + + + + + + + + NowDoc - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ NowDoc +

+ + + + +
+
+ +

+ + NowDoc + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new NowDoc() +

+
+ + + + + +
+

Defines a nowdoc string

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
label + + + + String + + + + + + + + +
raw + + + + String + + + + + + + + +
quote + + + + Boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Number.html b/docs/Number.html new file mode 100644 index 000000000..6ce32c5cb --- /dev/null +++ b/docs/Number.html @@ -0,0 +1,687 @@ + + + + + + + + + Number - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Number +

+ + + + +
+
+ +

+ + Number + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Number() +

+
+ + + + + +
+

Defines a numeric value

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/OffsetLookup.html b/docs/OffsetLookup.html new file mode 100644 index 000000000..288e359b5 --- /dev/null +++ b/docs/OffsetLookup.html @@ -0,0 +1,687 @@ + + + + + + + + + OffsetLookup - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ OffsetLookup +

+ + + + +
+
+ +

+ + OffsetLookup + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new OffsetLookup() +

+
+ + + + + +
+

Lookup on an offset in an array

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Operation.html b/docs/Operation.html new file mode 100644 index 000000000..534af2e48 --- /dev/null +++ b/docs/Operation.html @@ -0,0 +1,687 @@ + + + + + + + + + Operation - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Operation +

+ + + + +
+
+ +

+ + Operation + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Operation() +

+
+ + + + + +
+

Defines binary operations

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Parameter.html b/docs/Parameter.html new file mode 100644 index 000000000..b1a606c55 --- /dev/null +++ b/docs/Parameter.html @@ -0,0 +1,1028 @@ + + + + + + + + + Parameter - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Parameter +

+ + + + +
+
+ +

+ + Parameter + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Parameter() +

+
+ + + + + +
+

Defines a function parameter

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
type + + + + Identifier + + + | + + + null + + + + + + + + +
value + + + + Node + + + | + + + null + + + + + + + + +
byref + + + + boolean + + + + + + + + +
variadic + + + + boolean + + + + + + + + +
nullable + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ parseFlags(flags) → {void} +

+
+ + + + + +
+

Generic flags parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
flags + + + + Array.<Integer> + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/ParentReference.html b/docs/ParentReference.html new file mode 100644 index 000000000..c52c77834 --- /dev/null +++ b/docs/ParentReference.html @@ -0,0 +1,687 @@ + + + + + + + + + ParentReference - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ParentReference +

+ + + + +
+
+ +

+ + ParentReference + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new ParentReference() +

+
+ + + + + +
+

Defines a class reference node

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Parenthesis.html b/docs/Parenthesis.html new file mode 100644 index 000000000..176272af8 --- /dev/null +++ b/docs/Parenthesis.html @@ -0,0 +1,487 @@ + + + + + + + + + Parenthesis - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Parenthesis +

+ + + + +
+
+ +

+ + Parenthesis + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Parenthesis() +

+
+ + + + + +
+

Parenthesis encapsulation (... expr ...)

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
inner + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Position.html b/docs/Position.html new file mode 100644 index 000000000..49acda8ff --- /dev/null +++ b/docs/Position.html @@ -0,0 +1,378 @@ + + + + + + + + + Position - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Position +

+ + + + +
+
+ +

+ + Position + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Position() +

+
+ + + + + +
+

Each Position object consists of a line number (1-indexed) and a column number (0-indexed):

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
line + + + + Number + + + + + + + + +
column + + + + Number + + + + + + + + +
offset + + + + Number + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Post.html b/docs/Post.html new file mode 100644 index 000000000..57aa4d8a3 --- /dev/null +++ b/docs/Post.html @@ -0,0 +1,774 @@ + + + + + + + + + Post - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Post +

+ + + + +
+
+ +

+ + Post + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Post() +

+
+ + + + + +
+

Defines a post operation $i++ or $i--

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
type + + + + String + + + + + + + + +
what + + + + Variable + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Pre.html b/docs/Pre.html new file mode 100644 index 000000000..213450f9a --- /dev/null +++ b/docs/Pre.html @@ -0,0 +1,774 @@ + + + + + + + + + Pre - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Pre +

+ + + + +
+
+ +

+ + Pre + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Pre() +

+
+ + + + + +
+

Defines a pre operation ++$i or --$i

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
type + + + + String + + + + + + + + +
what + + + + Variable + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Print.html b/docs/Print.html new file mode 100644 index 000000000..f413a142e --- /dev/null +++ b/docs/Print.html @@ -0,0 +1,687 @@ + + + + + + + + + Print - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Print +

+ + + + +
+
+ +

+ + Print + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Print() +

+
+ + + + + +
+

Outputs

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Program.html b/docs/Program.html new file mode 100644 index 000000000..11de01093 --- /dev/null +++ b/docs/Program.html @@ -0,0 +1,827 @@ + + + + + + + + + Program - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Program +

+ + + + +
+
+ +

+ + Program + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Program() +

+
+ + + + + +
+

The main program node

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
errors + + + + Array.<Error> + + + + + + + + + + + + +
comments + + + + Array.<Doc> + + + + + + + + + + + <nullable>
+ +
+ +
tokens + + + + Array.<String> + + + + + + + + + + + <nullable>
+ +
+ +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Property.html b/docs/Property.html new file mode 100644 index 000000000..399df5d94 --- /dev/null +++ b/docs/Property.html @@ -0,0 +1,780 @@ + + + + + + + + + Property - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Property +

+ + + + +
+
+ +

+ + Property + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Property() +

+
+ + + + + +
+

Defines a class property

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + string + + + + + + + + +
value + + + + Node + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/PropertyLookup.html b/docs/PropertyLookup.html new file mode 100644 index 000000000..d4cf93f11 --- /dev/null +++ b/docs/PropertyLookup.html @@ -0,0 +1,687 @@ + + + + + + + + + PropertyLookup - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ PropertyLookup +

+ + + + +
+
+ +

+ + PropertyLookup + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new PropertyLookup() +

+
+ + + + + +
+

Lookup to an object property

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/PropertyStatement.html b/docs/PropertyStatement.html new file mode 100644 index 000000000..c5b3532e2 --- /dev/null +++ b/docs/PropertyStatement.html @@ -0,0 +1,891 @@ + + + + + + + + + PropertyStatement - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ PropertyStatement +

+ + + + +
+
+ +

+ + PropertyStatement + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new PropertyStatement() +

+
+ + + + + +
+

Declares a properties into the current scope

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
properties + + + + Array.<Property> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ parseFlags(flags) → {void} +

+
+ + + + + +
+

Generic flags parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
flags + + + + Array.<Integer> + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Reference.html b/docs/Reference.html new file mode 100644 index 000000000..12a00d66d --- /dev/null +++ b/docs/Reference.html @@ -0,0 +1,687 @@ + + + + + + + + + Reference - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Reference +

+ + + + +
+
+ +

+ + Reference + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Reference() +

+
+ + + + + +
+

Defines a reference node

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/RetIf.html b/docs/RetIf.html new file mode 100644 index 000000000..ced88f98d --- /dev/null +++ b/docs/RetIf.html @@ -0,0 +1,803 @@ + + + + + + + + + RetIf - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ RetIf +

+ + + + +
+
+ +

+ + RetIf + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new RetIf() +

+
+ + + + + +
+

Defines a short if statement that returns a value

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
test + + + + Expression + + + + + + + + +
trueExpr + + + + Expression + + + + + + + + +
falseExpr + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Return.html b/docs/Return.html new file mode 100644 index 000000000..65ec6ff44 --- /dev/null +++ b/docs/Return.html @@ -0,0 +1,751 @@ + + + + + + + + + Return - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Return +

+ + + + +
+
+ +

+ + Return + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Return() +

+
+ + + + + +
+

A continue statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
expr + + + + Expression + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/SelfReference.html b/docs/SelfReference.html new file mode 100644 index 000000000..6bcadc1e5 --- /dev/null +++ b/docs/SelfReference.html @@ -0,0 +1,687 @@ + + + + + + + + + SelfReference - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ SelfReference +

+ + + + +
+
+ +

+ + SelfReference + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new SelfReference() +

+
+ + + + + +
+

Defines a class reference node

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Silent.html b/docs/Silent.html new file mode 100644 index 000000000..c5580e449 --- /dev/null +++ b/docs/Silent.html @@ -0,0 +1,745 @@ + + + + + + + + + Silent - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Silent +

+ + + + +
+
+ +

+ + Silent + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Silent() +

+
+ + + + + +
+

Avoids to show/log warnings & notices from the inner expression

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
expr + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Statement.html b/docs/Statement.html new file mode 100644 index 000000000..07790815c --- /dev/null +++ b/docs/Statement.html @@ -0,0 +1,687 @@ + + + + + + + + + Statement - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Statement +

+ + + + +
+
+ +

+ + Statement + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Statement() +

+
+ + + + + +
+

Any statement.

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Static.html b/docs/Static.html new file mode 100644 index 000000000..3e6dd0df9 --- /dev/null +++ b/docs/Static.html @@ -0,0 +1,745 @@ + + + + + + + + + Static - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Static +

+ + + + +
+
+ +

+ + Static + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Static() +

+
+ + + + + +
+

Declares a static variable into the current scope

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
variables + + + + Array.<StaticVariable> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/StaticLookup.html b/docs/StaticLookup.html new file mode 100644 index 000000000..b21eb7eae --- /dev/null +++ b/docs/StaticLookup.html @@ -0,0 +1,687 @@ + + + + + + + + + StaticLookup - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ StaticLookup +

+ + + + +
+
+ +

+ + StaticLookup + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new StaticLookup() +

+
+ + + + + +
+

Lookup to a static property

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/StaticReference.html b/docs/StaticReference.html new file mode 100644 index 000000000..5d4225df8 --- /dev/null +++ b/docs/StaticReference.html @@ -0,0 +1,687 @@ + + + + + + + + + StaticReference - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ StaticReference +

+ + + + +
+
+ +

+ + StaticReference + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new StaticReference() +

+
+ + + + + +
+

Defines a class reference node

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/StaticVariable.html b/docs/StaticVariable.html new file mode 100644 index 000000000..6896cf16c --- /dev/null +++ b/docs/StaticVariable.html @@ -0,0 +1,798 @@ + + + + + + + + + StaticVariable - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ StaticVariable +

+ + + + +
+
+ +

+ + StaticVariable + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new StaticVariable() +

+
+ + + + + +
+

Defines a constant

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
variable + + + + Variable + + + + + + + + +
defaultValue + + + + Node + + + | + + + string + + + | + + + number + + + | + + + boolean + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/String.html b/docs/String.html new file mode 100644 index 000000000..d88cfb26e --- /dev/null +++ b/docs/String.html @@ -0,0 +1,785 @@ + + + + + + + + + String - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ String +

+ + + + +
+
+ +

+ + String + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new String() +

+
+ + + + + +
+

Defines a string (simple ou double quoted) - chars are already escaped

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
unicode + + + + boolean + + + + + + + + +
isDoubleQuote + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Switch.html b/docs/Switch.html new file mode 100644 index 000000000..613389778 --- /dev/null +++ b/docs/Switch.html @@ -0,0 +1,803 @@ + + + + + + + + + Switch - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Switch +

+ + + + +
+
+ +

+ + Switch + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Switch() +

+
+ + + + + +
+

Defines a switch statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
test + + + + Expression + + + + + + + + +
body + + + + Block + + + + + + + + +
shortForm + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Sys.html b/docs/Sys.html new file mode 100644 index 000000000..74ebd74e5 --- /dev/null +++ b/docs/Sys.html @@ -0,0 +1,642 @@ + + + + + + + + + Sys - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Sys +

+ + + + +
+
+ +

+ + Sys + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Sys() +

+
+ + + + + +
+

Defines system based call

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
arguments + + + + Array.<Node> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Throw.html b/docs/Throw.html new file mode 100644 index 000000000..d96395628 --- /dev/null +++ b/docs/Throw.html @@ -0,0 +1,745 @@ + + + + + + + + + Throw - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Throw +

+ + + + +
+
+ +

+ + Throw + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Throw() +

+
+ + + + + +
+

Defines a throw statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
what + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Trait.html b/docs/Trait.html new file mode 100644 index 000000000..6ad67f529 --- /dev/null +++ b/docs/Trait.html @@ -0,0 +1,900 @@ + + + + + + + + + Trait - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Trait +

+ + + + +
+
+ +

+ + Trait + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Trait() +

+
+ + + + + +
+

A trait definition

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
body + + + + Array.<Declaration> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ parseFlags(flags) → {void} +

+
+ + + + + +
+

Generic flags parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
flags + + + + Array.<Integer> + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/TraitAlias.html b/docs/TraitAlias.html new file mode 100644 index 000000000..47056112b --- /dev/null +++ b/docs/TraitAlias.html @@ -0,0 +1,850 @@ + + + + + + + + + TraitAlias - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ TraitAlias +

+ + + + +
+
+ +

+ + TraitAlias + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new TraitAlias() +

+
+ + + + + +
+

Defines a trait alias

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
trait + + + + Identifier + + + | + + + null + + + + + + + + +
method + + + + Identifier + + + + + + + + +
as + + + + Identifier + + + | + + + null + + + + + + + + +
visibility + + + + string + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/TraitPrecedence.html b/docs/TraitPrecedence.html new file mode 100644 index 000000000..4ca9f9788 --- /dev/null +++ b/docs/TraitPrecedence.html @@ -0,0 +1,809 @@ + + + + + + + + + TraitPrecedence - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ TraitPrecedence +

+ + + + +
+
+ +

+ + TraitPrecedence + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new TraitPrecedence() +

+
+ + + + + +
+

Defines a trait alias

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
trait + + + + Identifier + + + | + + + null + + + + + + + + +
method + + + + Identifier + + + + + + + + +
instead + + + + Array.<Identifier> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/TraitUse.html b/docs/TraitUse.html new file mode 100644 index 000000000..395ce8b46 --- /dev/null +++ b/docs/TraitUse.html @@ -0,0 +1,780 @@ + + + + + + + + + TraitUse - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ TraitUse +

+ + + + +
+
+ +

+ + TraitUse + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new TraitUse() +

+
+ + + + + +
+

Defines a trait usage

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
traits + + + + Array.<Identifier> + + + + + + + + +
adaptations + + + + Array.<Node> + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Try.html b/docs/Try.html new file mode 100644 index 000000000..ce2d968f7 --- /dev/null +++ b/docs/Try.html @@ -0,0 +1,803 @@ + + + + + + + + + Try - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Try +

+ + + + +
+
+ +

+ + Try + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Try() +

+
+ + + + + +
+

Defines a try statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
body + + + + Block + + + + + + + + +
catches + + + + Array.<Catch> + + + + + + + + +
always + + + + Block + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/TypeReference.html b/docs/TypeReference.html new file mode 100644 index 000000000..1b76732b5 --- /dev/null +++ b/docs/TypeReference.html @@ -0,0 +1,745 @@ + + + + + + + + + TypeReference - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ TypeReference +

+ + + + +
+
+ +

+ + TypeReference + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new TypeReference() +

+
+ + + + + +
+

Defines a class reference node

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + string + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Unary.html b/docs/Unary.html new file mode 100644 index 000000000..4d0139bc6 --- /dev/null +++ b/docs/Unary.html @@ -0,0 +1,774 @@ + + + + + + + + + Unary - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Unary +

+ + + + +
+
+ +

+ + Unary + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Unary() +

+
+ + + + + +
+

Unary operations

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
type + + + + String + + + + + + + + +
what + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Unset.html b/docs/Unset.html new file mode 100644 index 000000000..24e7c2522 --- /dev/null +++ b/docs/Unset.html @@ -0,0 +1,687 @@ + + + + + + + + + Unset - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Unset +

+ + + + +
+
+ +

+ + Unset + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Unset() +

+
+ + + + + +
+

Deletes references to a list of variables

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/UseGroup.html b/docs/UseGroup.html new file mode 100644 index 000000000..8b176cf78 --- /dev/null +++ b/docs/UseGroup.html @@ -0,0 +1,830 @@ + + + + + + + + + UseGroup - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ UseGroup +

+ + + + +
+
+ +

+ + UseGroup + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new UseGroup() +

+
+ + + + + +
+

Defines a use statement (with a list of use items)

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + String + + + | + + + null + + + + + + + + +
type + + + + String + + + | + + + null + + + + + + + +

Possible value : function, const

+
item + + + + Array.<UseItem> + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/UseItem.html b/docs/UseItem.html new file mode 100644 index 000000000..37f5035bc --- /dev/null +++ b/docs/UseItem.html @@ -0,0 +1,830 @@ + + + + + + + + + UseItem - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ UseItem +

+ + + + +
+
+ +

+ + UseItem + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new UseItem() +

+
+ + + + + +
+

Defines a use statement (from namespace)

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + String + + + + + + + + +
type + + + + String + + + | + + + null + + + + + + + +

Possible value : function, const

+
alias + + + + Identifier + + + | + + + null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Variable.html b/docs/Variable.html new file mode 100644 index 000000000..34c09ced8 --- /dev/null +++ b/docs/Variable.html @@ -0,0 +1,832 @@ + + + + + + + + + Variable - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Variable +

+ + + + +
+
+ +

+ + Variable + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Variable() +

+
+ + + + + +
+

Any expression node. Since the left-hand side of an assignment may +be any expression in general, an expression can also be a pattern.

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + + + String + + + | + + + Node + + + + + + + +

The variable name (can be a complex expression when the name is resolved dynamically)

+
byref + + + + boolean + + + + + + + +

Indicate if the variable reference is used, ex &$foo

+
curly + + + + boolean + + + + + + + +

Indicate if the name is defined between curlies, ex ${foo}

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + +
+ + + + + +
Example
+ + +
// PHP code :
+&$foo
+// AST output
+{
+ "kind": "variable",
+ "name": "foo",
+ "byref": true,
+ "curly": false
+}
+ + +
+ + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/While.html b/docs/While.html new file mode 100644 index 000000000..99b5f8bca --- /dev/null +++ b/docs/While.html @@ -0,0 +1,803 @@ + + + + + + + + + While - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ While +

+ + + + +
+
+ +

+ + While + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new While() +

+
+ + + + + +
+

Defines a while statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
test + + + + Expression + + + + + + + + +
body + + + + Statement + + + + + + + + +
shortForm + + + + boolean + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Yield.html b/docs/Yield.html new file mode 100644 index 000000000..bf3ce70dc --- /dev/null +++ b/docs/Yield.html @@ -0,0 +1,797 @@ + + + + + + + + + Yield - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Yield +

+ + + + +
+
+ +

+ + Yield + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new Yield() +

+
+ + + + + +
+

Defines a yield generator statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + + + Expression + + + | + + + Null + + + + + + + + +
key + + + + Expression + + + | + + + Null + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/YieldFrom.html b/docs/YieldFrom.html new file mode 100644 index 000000000..4ca8289fb --- /dev/null +++ b/docs/YieldFrom.html @@ -0,0 +1,756 @@ + + + + + + + + + YieldFrom - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ YieldFrom +

+ + + + +
+
+ +

+ + YieldFrom + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new YieldFrom() +

+
+ + + + + +
+

Defines a yield from generator statement

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/ast.js.html b/docs/ast.js.html new file mode 100644 index 000000000..b207724c2 --- /dev/null +++ b/docs/ast.js.html @@ -0,0 +1,714 @@ + + + + + + + + + + + ast.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Location = require("./ast/location");
+const Position = require("./ast/position");
+
+/**
+ * ## Class hierarchy
+ *
+ * - [Location](#location)
+ * - [Position](#position)
+ * - [Node](#node)
+ *   - [Noop](#noop)
+ *   - [StaticVariable](#staticvariable)
+ *   - [EncapsedPart](#encapsedpart)
+ *   - [Constant](#constant)
+ *   - [Identifier](#identifier)
+ *   - [Reference](#reference)
+ *     - [TypeReference](#classreference)
+ *     - [ParentReference](#classreference)
+ *     - [StaticReference](#classreference)
+ *     - [SelfReference](#classreference)
+ *     - [ClassReference](#classreference)
+ *   - [TraitUse](#traituse)
+ *   - [TraitAlias](#traitalias)
+ *   - [TraitPrecedence](#traitprecedence)
+ *   - [Comment](#comment)
+ *     - [CommentLine](#commentline)
+ *     - [CommentBlock](#commentblock)
+ *   - [Error](#error)
+ *   - [Expression](#expression)
+ *     - [Entry](#entry)
+ *     - [Closure](#closure)
+ *     - [Silent](#silent)
+ *     - [RetIf](#retif)
+ *     - [New](#new)
+ *     - [Include](#include)
+ *     - [Call](#call)
+ *     - [Eval](#eval)
+ *     - [Exit](#exit)
+ *     - [Clone](#clone)
+ *     - [Assign](#assign)
+ *     - [Array](#array)
+ *     - [List](#list)
+ *     - [Variable](#variable)
+ *     - [Variadic](#variadic)
+ *     - [Yield](#yield)
+ *     - [YieldFrom](#yieldfrom)
+ *     - [Print](#print)
+ *     - [Isset](#isset)
+ *     - [Empty](#empty)
+ *     - [Lookup](#lookup)
+ *       - [PropertyLookup](#propertylookup)
+ *       - [StaticLookup](#staticlookup)
+ *       - [OffsetLookup](#offsetlookup)
+ *     - [Operation](#operation)
+ *       - [Pre](#pre)
+ *       - [Post](#post)
+ *       - [Bin](#bin)
+ *       - [Unary](#unary)
+ *       - [Cast](#cast)
+ *     - [Literal](#literal)
+ *       - [Boolean](#boolean)
+ *       - [String](#string)
+ *       - [Number](#number)
+ *       - [Inline](#inline)
+ *       - [Magic](#magic)
+ *       - [Nowdoc](#nowdoc)
+ *       - [Encapsed](#encapsed)
+ *   - [Statement](#statement)
+ *     - [ConstantStatement](#constantstatement)
+ *       - [ClassConstant](#classconstant)
+ *     - [Return](#return)
+ *     - [Label](#label)
+ *     - [Continue](#continue)
+ *     - [Case](#case)
+ *     - [Break](#break)
+ *     - [Echo](#echo)
+ *     - [Unset](#unset)
+ *     - [Halt](#halt)
+ *     - [Declare](#declare)
+ *     - [Global](#global)
+ *     - [Static](#static)
+ *     - [If](#if)
+ *     - [Do](#do)
+ *     - [While](#while)
+ *     - [For](#for)
+ *     - [Foreach](#foreach)
+ *     - [Switch](#switch)
+ *     - [Goto](#goto)
+ *     - [Try](#try)
+ *     - [Catch](#catch)
+ *     - [Throw](#throw)
+ *     - [UseGroup](#usegroup)
+ *     - [UseItem](#useitem)
+ *     - [Block](#block)
+ *       - [Program](#program)
+ *       - [Namespace](#namespace)
+ *     - [PropertyStatement](#propertystatement)
+ *     - [Property](#property)
+ *     - [Declaration](#declaration)
+ *       - [Class](#class)
+ *       - [Interface](#interface)
+ *       - [Trait](#trait)
+ *       - [Function](#function)
+ *         - [Method](#method)
+ *       - [Parameter](#parameter)
+ * ---
+ */
+
+/**
+ * The AST builder class
+ * @constructor AST
+ * @tutorial AST
+ * @property {Boolean} withPositions - Should locate any node (by default false)
+ * @property {Boolean} withSource - Should extract the node original code (by default false)
+ */
+const AST = function(withPositions, withSource) {
+  this.withPositions = withPositions;
+  this.withSource = withSource;
+};
+
+/**
+ * Create a position node from specified parser
+ * including it's lexer current state
+ * @param {Parser}
+ * @return {Position}
+ * @private
+ */
+AST.prototype.position = function(parser) {
+  return new Position(
+    parser.lexer.yylloc.first_line,
+    parser.lexer.yylloc.first_column,
+    parser.lexer.yylloc.first_offset
+  );
+};
+
+// operators in ascending order of precedence
+AST.precedence = {};
+[
+  ["or"],
+  ["xor"],
+  ["and"],
+  ["="],
+  ["?"],
+  ["??"],
+  ["||"],
+  ["&&"],
+  ["|"],
+  ["^"],
+  ["&"],
+  ["==", "!=", "===", "!==", /* '<>', */ "<=>"],
+  ["<", "<=", ">", ">="],
+  ["<<", ">>"],
+  ["+", "-", "."],
+  ["*", "/", "%"],
+  ["!"],
+  ["instanceof"],
+  ["cast"]
+  // TODO: typecasts
+  // TODO: [ (array)
+  // TODO: clone, new
+].forEach(function(list, index) {
+  list.forEach(function(operator) {
+    AST.precedence[operator] = index + 1;
+  });
+});
+
+/**
+ * Change parent node informations after swapping childs
+ */
+AST.prototype.swapLocations = function(target, first, last, parser) {
+  if (this.withPositions) {
+    target.loc.start = first.loc.start;
+    target.loc.end = last.loc.end;
+    if (this.withSource) {
+      target.loc.source = parser.lexer._input.substring(
+        target.loc.start.offset,
+        target.loc.end.offset
+      );
+    }
+  }
+};
+
+/**
+ * Includes locations from first & last into the target
+ */
+AST.prototype.resolveLocations = function(target, first, last, parser) {
+  if (this.withPositions) {
+    if (target.loc.start.offset > first.loc.start.offset) {
+      target.loc.start = first.loc.start;
+    }
+    if (target.loc.end.offset < last.loc.end.offset) {
+      target.loc.end = last.loc.end;
+    }
+    if (this.withSource) {
+      target.loc.source = parser.lexer._input.substring(
+        target.loc.start.offset,
+        target.loc.end.offset
+      );
+    }
+  }
+};
+
+/**
+ * Check and fix precence, by default using right
+ */
+AST.prototype.resolvePrecedence = function(result, parser) {
+  let buffer, lLevel, rLevel;
+  // handling precendence
+  if (result.kind === "call") {
+    // including what argument into location
+    this.resolveLocations(result, result.what, result, parser);
+  } else if (
+    result.kind === "propertylookup" ||
+    result.kind === "staticlookup" ||
+    (result.kind === "offsetlookup" && result.offset)
+  ) {
+    // including what argument into location
+    this.resolveLocations(result, result.what, result.offset, parser);
+  } else if (result.kind === "bin") {
+    if (result.right && !result.right.parenthesizedExpression) {
+      if (result.right.kind === "bin") {
+        lLevel = AST.precedence[result.type];
+        rLevel = AST.precedence[result.right.type];
+        if (lLevel && rLevel && rLevel <= lLevel) {
+          // https://github.com/glayzzle/php-parser/issues/79
+          // shift precedence
+          buffer = result.right;
+          result.right = result.right.left;
+          this.swapLocations(result, result.left, result.right, parser);
+          buffer.left = this.resolvePrecedence(result, parser);
+          result = buffer;
+        }
+      } else if (result.right.kind === "retif") {
+        lLevel = AST.precedence[result.type];
+        rLevel = AST.precedence["?"];
+        if (lLevel && rLevel && rLevel <= lLevel) {
+          buffer = result.right;
+          result.right = result.right.test;
+          this.swapLocations(result, result.left, result.right, parser);
+          buffer.test = this.resolvePrecedence(result, parser);
+          this.swapLocations(buffer, buffer.test, buffer.falseExpr, parser);
+          result = buffer;
+        }
+      }
+    }
+  } else if (
+    result.kind === "cast" &&
+    result.what &&
+    !result.what.parenthesizedExpression
+  ) {
+    // https://github.com/glayzzle/php-parser/issues/172
+    if (result.what.kind === "bin") {
+      buffer = result.what;
+      result.what = result.what.left;
+      this.swapLocations(result, result, result.what, parser);
+      buffer.left = this.resolvePrecedence(result, parser);
+      this.swapLocations(buffer, buffer.left, buffer.right, parser);
+      result = buffer;
+    } else if (result.what.kind === "retif") {
+      buffer = result.what;
+      result.what = result.what.test;
+      this.swapLocations(result, result, result.what, parser);
+      buffer.test = this.resolvePrecedence(result, parser);
+      this.swapLocations(buffer, buffer.test, buffer.falseExpr, parser);
+      result = buffer;
+    }
+  } else if (result.kind === "unary") {
+    // https://github.com/glayzzle/php-parser/issues/75
+    if (result.what && !result.what.parenthesizedExpression) {
+      // unary precedence is always lower
+      if (result.what.kind === "bin") {
+        buffer = result.what;
+        result.what = result.what.left;
+        this.swapLocations(result, result, result.what, parser);
+        buffer.left = this.resolvePrecedence(result, parser);
+        this.swapLocations(buffer, buffer.left, buffer.right, parser);
+        result = buffer;
+      } else if (result.what.kind === "retif") {
+        buffer = result.what;
+        result.what = result.what.test;
+        this.swapLocations(result, result, result.what, parser);
+        buffer.test = this.resolvePrecedence(result, parser);
+        this.swapLocations(buffer, buffer.test, buffer.falseExpr, parser);
+        result = buffer;
+      }
+    }
+  } else if (result.kind === "retif") {
+    // https://github.com/glayzzle/php-parser/issues/77
+    if (
+      result.falseExpr &&
+      result.falseExpr.kind === "retif" &&
+      !result.falseExpr.parenthesizedExpression
+    ) {
+      buffer = result.falseExpr;
+      result.falseExpr = buffer.test;
+      this.swapLocations(result, result.test, result.falseExpr, parser);
+      buffer.test = this.resolvePrecedence(result, parser);
+      this.swapLocations(buffer, buffer.test, buffer.falseExpr, parser);
+      result = buffer;
+    }
+  } else if (result.kind === "assign") {
+    // https://github.com/glayzzle/php-parser/issues/81
+    if (
+      result.right &&
+      result.right.kind === "bin" &&
+      !result.right.parenthesizedExpression
+    ) {
+      lLevel = AST.precedence["="];
+      rLevel = AST.precedence[result.right.type];
+      // only shifts with and, xor, or
+      if (lLevel && rLevel && rLevel < lLevel) {
+        buffer = result.right;
+        result.right = result.right.left;
+        buffer.left = result;
+        this.swapLocations(buffer, buffer.left, result.right, parser);
+        result = buffer;
+      }
+    }
+  } else if (
+    result.kind === "silent" &&
+    result.expr.right &&
+    !result.expr.parenthesizedExpression
+  ) {
+    // overall least precedence
+    buffer = result.expr;
+    result.expr = buffer.left;
+    buffer.left = result;
+    this.swapLocations(buffer, buffer.left, buffer.right, parser);
+    result = buffer;
+  }
+  return result;
+};
+
+/**
+ * Prepares an AST node
+ * @param {String|null} kind - Defines the node type
+ * (if null, the kind must be passed at the function call)
+ * @param {Parser} parser - The parser instance (use for extracting locations)
+ * @return {Function}
+ */
+AST.prototype.prepare = function(kind, docs, parser) {
+  let start = null;
+  if (this.withPositions || this.withSource) {
+    start = this.position(parser);
+  }
+  const self = this;
+  // returns the node
+  const result = function() {
+    let location = null;
+    const args = Array.prototype.slice.call(arguments);
+    args.push(docs);
+    if (typeof result.preBuild === "function") {
+      result.preBuild(arguments);
+    }
+    if (self.withPositions || self.withSource) {
+      let src = null;
+      if (self.withSource) {
+        src = parser.lexer._input.substring(start.offset, parser.prev[2]);
+      }
+      if (self.withPositions) {
+        location = new Location(
+          src,
+          start,
+          new Position(parser.prev[0], parser.prev[1], parser.prev[2])
+        );
+      } else {
+        location = new Location(src, null, null);
+      }
+      // last argument is always the location
+      args.push(location);
+    }
+    // handle lazy kind definitions
+    if (!kind) {
+      kind = args.shift();
+    }
+    // build the object
+    const node = self[kind];
+    if (typeof node !== "function") {
+      throw new Error('Undefined node "' + kind + '"');
+    }
+    const astNode = Object.create(node.prototype);
+    node.apply(astNode, args);
+    result.instance = astNode;
+    if (result.trailingComments) {
+      // buffer of trailingComments
+      astNode.trailingComments = result.trailingComments;
+    }
+    if (typeof result.postBuild === "function") {
+      result.postBuild(astNode);
+    }
+    if (parser.debug) {
+      delete AST.stack[result.stackUid];
+    }
+    return self.resolvePrecedence(astNode, parser);
+  };
+  if (parser.debug) {
+    if (!AST.stack) {
+      AST.stack = {};
+      AST.stackUid = 1;
+    }
+    AST.stack[++AST.stackUid] = {
+      position: start,
+      stack: new Error().stack.split("\n").slice(3, 5)
+    };
+    result.stackUid = AST.stackUid;
+  }
+
+  /**
+   * Helper to change a node kind
+   * @param {String} newKind
+   */
+  result.setKind = function(newKind) {
+    kind = newKind;
+  };
+  /**
+   * Sets a list of trailing comments
+   * @param {*} docs
+   */
+  result.setTrailingComments = function(docs) {
+    if (result.instance) {
+      // already created
+      result.instance.setTrailingComments(docs);
+    } else {
+      result.trailingComments = docs;
+    }
+  };
+
+  /**
+   * Release a node without using it on the AST
+   */
+  result.destroy = function(target) {
+    if (docs) {
+      // release current docs stack
+      if (target) {
+        if (!target.leadingComments) {
+          target.leadingComments = docs;
+        } else {
+          target.leadingComments = docs.concat(target.leadingComments);
+        }
+      } else {
+        parser._docIndex = parser._docs.length - docs.length;
+      }
+    }
+    if (parser.debug) {
+      delete AST.stack[result.stackUid];
+    }
+  };
+  return result;
+};
+
+AST.prototype.checkNodes = function() {
+  const errors = [];
+  for (const k in AST.stack) {
+    if (AST.stack.hasOwnProperty(k)) {
+      errors.push(AST.stack[k]);
+    }
+  }
+  AST.stack = {};
+  return errors;
+};
+
+// Define all AST nodes
+[
+  require("./ast/array"),
+  require("./ast/assign"),
+  require("./ast/bin"),
+  require("./ast/block"),
+  require("./ast/boolean"),
+  require("./ast/break"),
+  require("./ast/call"),
+  require("./ast/case"),
+  require("./ast/cast"),
+  require("./ast/catch"),
+  require("./ast/class"),
+  require("./ast/classconstant"),
+  require("./ast/classreference"),
+  require("./ast/clone"),
+  require("./ast/closure"),
+  require("./ast/comment"),
+  require("./ast/commentblock"),
+  require("./ast/commentline"),
+  require("./ast/constant"),
+  require("./ast/constantstatement"),
+  require("./ast/continue"),
+  require("./ast/declaration"),
+  require("./ast/declare"),
+  require("./ast/declaredirective"),
+  require("./ast/do"),
+  require("./ast/echo"),
+  require("./ast/empty"),
+  require("./ast/encapsed"),
+  require("./ast/encapsedpart"),
+  require("./ast/entry"),
+  require("./ast/error"),
+  require("./ast/eval"),
+  require("./ast/exit"),
+  require("./ast/expression"),
+  require("./ast/expressionstatement"),
+  require("./ast/for"),
+  require("./ast/foreach"),
+  require("./ast/function"),
+  require("./ast/global"),
+  require("./ast/goto"),
+  require("./ast/halt"),
+  require("./ast/identifier"),
+  require("./ast/if"),
+  require("./ast/include"),
+  require("./ast/inline"),
+  require("./ast/interface"),
+  require("./ast/isset"),
+  require("./ast/label"),
+  require("./ast/list"),
+  require("./ast/literal"),
+  require("./ast/lookup"),
+  require("./ast/magic"),
+  require("./ast/method"),
+  require("./ast/namespace"),
+  require("./ast/new"),
+  require("./ast/node"),
+  require("./ast/noop"),
+  require("./ast/nowdoc"),
+  require("./ast/number"),
+  require("./ast/offsetlookup"),
+  require("./ast/operation"),
+  require("./ast/parameter"),
+  require("./ast/parentreference"),
+  require("./ast/post"),
+  require("./ast/pre"),
+  require("./ast/print"),
+  require("./ast/program"),
+  require("./ast/property"),
+  require("./ast/propertylookup"),
+  require("./ast/propertystatement"),
+  require("./ast/reference"),
+  require("./ast/retif"),
+  require("./ast/return"),
+  require("./ast/selfreference"),
+  require("./ast/silent"),
+  require("./ast/statement"),
+  require("./ast/static"),
+  require("./ast/staticvariable"),
+  require("./ast/staticlookup"),
+  require("./ast/staticreference"),
+  require("./ast/string"),
+  require("./ast/switch"),
+  require("./ast/throw"),
+  require("./ast/trait"),
+  require("./ast/traitalias"),
+  require("./ast/traitprecedence"),
+  require("./ast/traituse"),
+  require("./ast/try"),
+  require("./ast/typereference"),
+  require("./ast/unary"),
+  require("./ast/unset"),
+  require("./ast/usegroup"),
+  require("./ast/useitem"),
+  require("./ast/variable"),
+  require("./ast/variadic"),
+  require("./ast/while"),
+  require("./ast/yield"),
+  require("./ast/yieldfrom")
+].forEach(function(ctor) {
+  AST.prototype[ctor.kind] = ctor;
+});
+
+module.exports = AST;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_array.js.html b/docs/ast_array.js.html new file mode 100644 index 000000000..77bcce525 --- /dev/null +++ b/docs/ast_array.js.html @@ -0,0 +1,187 @@ + + + + + + + + + + + ast/array.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/array.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expr = require("./expression");
+const KIND = "array";
+
+/**
+ * Defines an array structure
+ * @constructor Array
+ * @example
+ * // PHP code :
+ * [1, 'foo' => 'bar', 3]
+ *
+ * // AST structure :
+ * {
+ *  "kind": "array",
+ *  "shortForm": true
+ *  "items": [
+ *    {"kind": "number", "value": "1"},
+ *    {
+ *      "kind": "entry",
+ *      "key": {"kind": "string", "value": "foo", "isDoubleQuote": false},
+ *      "value": {"kind": "string", "value": "bar", "isDoubleQuote": false}
+ *    },
+ *    {"kind": "number", "value": "3"}
+ *  ]
+ * }
+ * @extends {Expression}
+ * @property {Entry|Expr|Variable} items List of array items
+ * @property {boolean} shortForm Indicate if the short array syntax is used, ex `[]` instead `array()`
+ */
+module.exports = Expr.extends(KIND, function Array(
+  shortForm,
+  items,
+  docs,
+  location
+) {
+  Expr.apply(this, [KIND, docs, location]);
+  this.items = items;
+  this.shortForm = shortForm;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_assign.js.html b/docs/ast_assign.js.html new file mode 100644 index 000000000..c80e440a0 --- /dev/null +++ b/docs/ast_assign.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/assign.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/assign.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "assign";
+
+/**
+ * Assigns a value to the specified target
+ * @constructor Assign
+ * @extends {Expression}
+ * @property {Expression} left
+ * @property {Expression} right
+ * @property {String} operator
+ */
+module.exports = Expression.extends(KIND, function Assign(
+  left,
+  right,
+  operator,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.operator = operator;
+  this.left = left;
+  this.right = right;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_bin.js.html b/docs/ast_bin.js.html new file mode 100644 index 000000000..2b77f1327 --- /dev/null +++ b/docs/ast_bin.js.html @@ -0,0 +1,171 @@ + + + + + + + + + + + ast/bin.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/bin.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Operation = require("./operation");
+const KIND = "bin";
+/**
+ * Binary operations
+ * @constructor Bin
+ * @extends {Operation}
+ * @property {String} type
+ * @property {Expression} left
+ * @property {Expression} right
+ */
+module.exports = Operation.extends(KIND, function Bin(
+  type,
+  left,
+  right,
+  docs,
+  location
+) {
+  Operation.apply(this, [KIND, docs, location]);
+  this.type = type;
+  this.left = left;
+  this.right = right;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_block.js.html b/docs/ast_block.js.html new file mode 100644 index 000000000..6f6ba46c4 --- /dev/null +++ b/docs/ast_block.js.html @@ -0,0 +1,167 @@ + + + + + + + + + + + ast/block.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/block.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "block";
+
+/**
+ * A block statement, i.e., a sequence of statements surrounded by braces.
+ * @constructor Block
+ * @extends {Statement}
+ * @property {Node[]} children
+ */
+module.exports = Statement.extends(KIND, function Block(
+  kind,
+  children,
+  docs,
+  location
+) {
+  Statement.apply(this, [kind || KIND, docs, location]);
+  this.children = children.filter(Boolean);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_boolean.js.html b/docs/ast_boolean.js.html new file mode 100644 index 000000000..3decc2773 --- /dev/null +++ b/docs/ast_boolean.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/boolean.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/boolean.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Literal = require("./literal");
+const KIND = "boolean";
+
+/**
+ * Defines a boolean value (true/false)
+ * @constructor Boolean
+ * @extends {Literal}
+ */
+module.exports = Literal.extends(KIND, function Boolean(
+  value,
+  raw,
+  docs,
+  location
+) {
+  Literal.apply(this, [KIND, value, raw, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_break.js.html b/docs/ast_break.js.html new file mode 100644 index 000000000..fde186ed3 --- /dev/null +++ b/docs/ast_break.js.html @@ -0,0 +1,162 @@ + + + + + + + + + + + ast/break.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/break.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "break";
+
+/**
+ * A break statement
+ * @constructor Break
+ * @extends {Statement}
+ * @property {Number|Null} level
+ */
+module.exports = Statement.extends(KIND, function Break(level, docs, location) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.level = level;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_call.js.html b/docs/ast_call.js.html new file mode 100644 index 000000000..5a77c9372 --- /dev/null +++ b/docs/ast_call.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/call.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/call.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "call";
+
+/**
+ * Executes a call statement
+ * @constructor Call
+ * @extends {Expression}
+ * @property {Identifier|Variable|??} what
+ * @property {Arguments[]} arguments
+ */
+module.exports = Expression.extends(KIND, function Call(
+  what,
+  args,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.what = what;
+  this.arguments = args;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_case.js.html b/docs/ast_case.js.html new file mode 100644 index 000000000..5377108c9 --- /dev/null +++ b/docs/ast_case.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/case.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/case.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "case";
+
+/**
+ * A switch case statement
+ * @constructor Case
+ * @extends {Statement}
+ * @property {Expression|null} test - if null, means that the default case
+ * @property {Block|null} body
+ */
+module.exports = Statement.extends(KIND, function Case(
+  test,
+  body,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.test = test;
+  this.body = body;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_cast.js.html b/docs/ast_cast.js.html new file mode 100644 index 000000000..c43064b48 --- /dev/null +++ b/docs/ast_cast.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/cast.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/cast.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Operation = require("./operation");
+const KIND = "cast";
+
+/**
+ * Binary operations
+ * @constructor Cast
+ * @extends {Operation}
+ * @property {String} type
+ * @property {String} raw
+ * @property {Expression} what
+ */
+module.exports = Operation.extends(KIND, function Cast(
+  type,
+  raw,
+  what,
+  docs,
+  location
+) {
+  Operation.apply(this, [KIND, docs, location]);
+  this.type = type;
+  this.raw = raw;
+  this.what = what;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_catch.js.html b/docs/ast_catch.js.html new file mode 100644 index 000000000..d439aa1e5 --- /dev/null +++ b/docs/ast_catch.js.html @@ -0,0 +1,173 @@ + + + + + + + + + + + ast/catch.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/catch.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "catch";
+
+/**
+ * Defines a catch statement
+ * @constructor Catch
+ * @extends {Statement}
+ * @property {Identifier[]} what
+ * @property {Variable} variable
+ * @property {Statement} body
+ * @see http://php.net/manual/en/language.exceptions.php
+ */
+module.exports = Statement.extends(KIND, function Catch(
+  body,
+  what,
+  variable,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.body = body;
+  this.what = what;
+  this.variable = variable;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_class.js.html b/docs/ast_class.js.html new file mode 100644 index 000000000..559a82081 --- /dev/null +++ b/docs/ast_class.js.html @@ -0,0 +1,179 @@ + + + + + + + + + + + ast/class.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/class.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Declaration = require("./declaration");
+const KIND = "class";
+
+/**
+ * A class definition
+ * @constructor Class
+ * @extends {Declaration}
+ * @property {Identifier|null} extends
+ * @property {Identifier[]} implements
+ * @property {Declaration[]} body
+ * @property {boolean} isAnonymous
+ * @property {boolean} isAbstract
+ * @property {boolean} isFinal
+ */
+module.exports = Declaration.extends(KIND, function Class(
+  name,
+  ext,
+  impl,
+  body,
+  flags,
+  docs,
+  location
+) {
+  Declaration.apply(this, [KIND, name, docs, location]);
+  this.isAnonymous = name ? false : true;
+  this.extends = ext;
+  this.implements = impl;
+  this.body = body;
+  this.parseFlags(flags);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_classconstant.js.html b/docs/ast_classconstant.js.html new file mode 100644 index 000000000..93821872a --- /dev/null +++ b/docs/ast_classconstant.js.html @@ -0,0 +1,194 @@ + + + + + + + + + + + ast/classconstant.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/classconstant.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const ConstantStatement = require("./constantstatement");
+const KIND = "classconstant";
+
+const IS_UNDEFINED = "";
+const IS_PUBLIC = "public";
+const IS_PROTECTED = "protected";
+const IS_PRIVATE = "private";
+
+/**
+ * Defines a class/interface/trait constant
+ * @constructor ClassConstant
+ * @extends {ConstantStatement}
+ * @property {string} visibility
+ */
+const ClassConstant = ConstantStatement.extends(KIND, function ClassConstant(
+  kind,
+  constants,
+  flags,
+  docs,
+  location
+) {
+  ConstantStatement.apply(this, [kind || KIND, constants, docs, location]);
+  this.parseFlags(flags);
+});
+
+/**
+ * Generic flags parser
+ * @param {Integer[]} flags
+ * @return {void}
+ */
+ClassConstant.prototype.parseFlags = function(flags) {
+  if (flags[0] === -1) {
+    this.visibility = IS_UNDEFINED;
+  } else if (flags[0] === null) {
+    this.visibility = null;
+  } else if (flags[0] === 0) {
+    this.visibility = IS_PUBLIC;
+  } else if (flags[0] === 1) {
+    this.visibility = IS_PROTECTED;
+  } else if (flags[0] === 2) {
+    this.visibility = IS_PRIVATE;
+  }
+};
+
+module.exports = ClassConstant;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_classreference.js.html b/docs/ast_classreference.js.html new file mode 100644 index 000000000..95c44bd7b --- /dev/null +++ b/docs/ast_classreference.js.html @@ -0,0 +1,202 @@ + + + + + + + + + + + ast/classreference.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/classreference.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Reference = require("./reference");
+const KIND = "classreference";
+
+/**
+ * Defines a class reference node
+ * @constructor ClassReference
+ * @extends {Reference}
+ * @property {string} name
+ * @property {string} resolution
+ */
+const ClassReference = Reference.extends(KIND, function ClassReference(
+  name,
+  isRelative,
+  docs,
+  location
+) {
+  Reference.apply(this, [KIND, docs, location]);
+  if (isRelative) {
+    this.resolution = ClassReference.RELATIVE_NAME;
+  } else if (name.length === 1) {
+    this.resolution = ClassReference.UNQUALIFIED_NAME;
+  } else if (!name[0]) {
+    this.resolution = ClassReference.FULL_QUALIFIED_NAME;
+  } else {
+    this.resolution = ClassReference.QUALIFIED_NAME;
+  }
+  this.name = name.join("\\");
+});
+
+/**
+ * This is an identifier without a namespace separator, such as Foo
+ * @constant {String} UNQUALIFIED_NAME
+ */
+ClassReference.UNQUALIFIED_NAME = "uqn";
+/**
+ * This is an identifier with a namespace separator, such as Foo\Bar
+ * @constant {String} QUALIFIED_NAME
+ */
+ClassReference.QUALIFIED_NAME = "qn";
+/**
+ * This is an identifier with a namespace separator that begins with
+ * a namespace separator, such as \Foo\Bar. The namespace \Foo is also
+ * a fully qualified name.
+ * @constant {String} FULL_QUALIFIED_NAME
+ */
+ClassReference.FULL_QUALIFIED_NAME = "fqn";
+/**
+ * This is an identifier starting with namespace, such as namespace\Foo\Bar.
+ * @constant {String} RELATIVE_NAME
+ */
+ClassReference.RELATIVE_NAME = "rn";
+
+module.exports = ClassReference;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_clone.js.html b/docs/ast_clone.js.html new file mode 100644 index 000000000..8e11034cf --- /dev/null +++ b/docs/ast_clone.js.html @@ -0,0 +1,162 @@ + + + + + + + + + + + ast/clone.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/clone.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "clone";
+
+/**
+ * Defines a clone call
+ * @constructor Clone
+ * @extends {Expression}
+ * @property {Expression} what
+ */
+module.exports = Expression.extends(KIND, function Clone(what, docs, location) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.what = what;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_closure.js.html b/docs/ast_closure.js.html new file mode 100644 index 000000000..ecf56ef82 --- /dev/null +++ b/docs/ast_closure.js.html @@ -0,0 +1,183 @@ + + + + + + + + + + + ast/closure.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/closure.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "closure";
+
+/**
+ * Defines a closure
+ * @constructor Closure
+ * @extends {Expression}
+ * @property {Parameter[]} arguments
+ * @property {Variable[]} uses
+ * @property {Identifier} type
+ * @property {boolean} byref
+ * @property {boolean} nullable
+ * @property {Block|null} body
+ * @property {boolean} isStatic
+ */
+module.exports = Expression.extends(KIND, function Closure(
+  args,
+  byref,
+  uses,
+  type,
+  nullable,
+  isStatic,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.uses = uses;
+  this.arguments = args;
+  this.byref = byref;
+  this.type = type;
+  this.nullable = nullable;
+  this.isStatic = isStatic || false;
+  this.body = null;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_comment.js.html b/docs/ast_comment.js.html new file mode 100644 index 000000000..6e9846f39 --- /dev/null +++ b/docs/ast_comment.js.html @@ -0,0 +1,166 @@ + + + + + + + + + + + ast/comment.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/comment.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+
+/**
+ * Abstract documentation node (ComentLine or CommentBlock)
+ * @constructor Comment
+ * @extends {Node}
+ * @property {String} value
+ */
+module.exports = Node.extends("comment", function Comment(
+  kind,
+  value,
+  docs,
+  location
+) {
+  Node.apply(this, [kind, docs, location]);
+  this.value = value;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_commentblock.js.html b/docs/ast_commentblock.js.html new file mode 100644 index 000000000..9ba7812e6 --- /dev/null +++ b/docs/ast_commentblock.js.html @@ -0,0 +1,164 @@ + + + + + + + + + + + ast/commentblock.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/commentblock.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Comment = require("./comment");
+const KIND = "commentblock";
+
+/**
+ * A comment block (multiline)
+ * @constructor CommentBlock
+ * @extends {Comment}
+ */
+module.exports = Comment.extends(KIND, function CommentBlock(
+  value,
+  docs,
+  location
+) {
+  Comment.apply(this, [KIND, value, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_commentline.js.html b/docs/ast_commentline.js.html new file mode 100644 index 000000000..744b84223 --- /dev/null +++ b/docs/ast_commentline.js.html @@ -0,0 +1,164 @@ + + + + + + + + + + + ast/commentline.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/commentline.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Comment = require("./comment");
+const KIND = "commentline";
+
+/**
+ * A single line comment
+ * @constructor CommentLine
+ * @extends {Comment}
+ */
+module.exports = Comment.extends(KIND, function CommentLine(
+  value,
+  docs,
+  location
+) {
+  Comment.apply(this, [KIND, value, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_constant.js.html b/docs/ast_constant.js.html new file mode 100644 index 000000000..cffcc245b --- /dev/null +++ b/docs/ast_constant.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/constant.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/constant.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "constant";
+
+/**
+ * Defines a constant
+ * @constructor Constant
+ * @extends {Node}
+ * @property {string} name
+ * @property {Node|string|number|boolean|null} value
+ */
+module.exports = Node.extends(KIND, function Constant(
+  name,
+  value,
+  docs,
+  location
+) {
+  Node.apply(this, [KIND, docs, location]);
+  this.name = name;
+  this.value = value;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_constantstatement.js.html b/docs/ast_constantstatement.js.html new file mode 100644 index 000000000..b4b9efe95 --- /dev/null +++ b/docs/ast_constantstatement.js.html @@ -0,0 +1,167 @@ + + + + + + + + + + + ast/constantstatement.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/constantstatement.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "constantstatement";
+
+/**
+ * Declares a constants into the current scope
+ * @constructor ConstantStatement
+ * @extends {Statement}
+ * @property {Constant[]} constants
+ */
+module.exports = Statement.extends(KIND, function ConstantStatement(
+  kind,
+  constants,
+  docs,
+  location
+) {
+  Statement.apply(this, [kind || KIND, docs, location]);
+  this.constants = constants;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_constref.js.html b/docs/ast_constref.js.html new file mode 100644 index 000000000..7ee584444 --- /dev/null +++ b/docs/ast_constref.js.html @@ -0,0 +1,163 @@ + + + + + + + + + + + ast/constref.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/constref.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expr = require("./expression");
+const KIND = "constref";
+
+/**
+ * A constant reference
+ * @constructor ConstRef
+ * @extends {Expression}
+ * @property {String|Node} name
+ */
+module.exports = Expr.extends(KIND, function ConstRef(
+  identifier,
+  docs,
+  location
+) {
+  Expr.apply(this, [KIND, docs, location]);
+  this.name = identifier;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_continue.js.html b/docs/ast_continue.js.html new file mode 100644 index 000000000..0d99bb8c9 --- /dev/null +++ b/docs/ast_continue.js.html @@ -0,0 +1,166 @@ + + + + + + + + + + + ast/continue.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/continue.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "continue";
+
+/**
+ * A continue statement
+ * @constructor Continue
+ * @extends {Statement}
+ * @property {Number|Null} level
+ */
+module.exports = Statement.extends(KIND, function Continue(
+  level,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.level = level;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_declaration.js.html b/docs/ast_declaration.js.html new file mode 100644 index 000000000..aa35d6fd2 --- /dev/null +++ b/docs/ast_declaration.js.html @@ -0,0 +1,198 @@ + + + + + + + + + + + ast/declaration.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/declaration.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "declaration";
+
+const IS_UNDEFINED = "";
+const IS_PUBLIC = "public";
+const IS_PROTECTED = "protected";
+const IS_PRIVATE = "private";
+
+/**
+ * A declaration statement (function, class, interface...)
+ * @constructor Declaration
+ * @extends {Statement}
+ * @property {Identifier|string} name
+ */
+const Declaration = Statement.extends(KIND, function Declaration(
+  kind,
+  name,
+  docs,
+  location
+) {
+  Statement.apply(this, [kind || KIND, docs, location]);
+  this.name = name;
+});
+
+/**
+ * Generic flags parser
+ * @param {Integer[]} flags
+ * @return {void}
+ */
+Declaration.prototype.parseFlags = function(flags) {
+  this.isAbstract = flags[2] === 1;
+  this.isFinal = flags[2] === 2;
+  if (this.kind !== "class") {
+    if (flags[0] === -1) {
+      this.visibility = IS_UNDEFINED;
+    } else if (flags[0] === null) {
+      this.visibility = null;
+    } else if (flags[0] === 0) {
+      this.visibility = IS_PUBLIC;
+    } else if (flags[0] === 1) {
+      this.visibility = IS_PROTECTED;
+    } else if (flags[0] === 2) {
+      this.visibility = IS_PRIVATE;
+    }
+    this.isStatic = flags[1] === 1;
+  }
+};
+
+module.exports = Declaration;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_declare.js.html b/docs/ast_declare.js.html new file mode 100644 index 000000000..77ac6681d --- /dev/null +++ b/docs/ast_declare.js.html @@ -0,0 +1,212 @@ + + + + + + + + + + + ast/declare.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/declare.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Block = require("./block");
+const KIND = "declare";
+
+/**
+ * The declare construct is used to set execution directives for a block of code
+ * @constructor Declare
+ * @extends {Block}
+ * @property {Array[]} directives
+ * @property {String} mode
+ * @see http://php.net/manual/en/control-structures.declare.php
+ */
+const Declare = Block.extends(KIND, function Declare(
+  directives,
+  body,
+  mode,
+  docs,
+  location
+) {
+  Block.apply(this, [KIND, body, docs, location]);
+  this.directives = directives;
+  this.mode = mode;
+});
+
+/**
+ * The node is declared as a short tag syntax :
+ * ```php
+ * <?php
+ * declare(ticks=1):
+ * // some statements
+ * enddeclare;
+ * ```
+ * @constant {String} MODE_SHORT
+ */
+Declare.MODE_SHORT = "short";
+
+/**
+ * The node is declared bracket enclosed code :
+ * ```php
+ * <?php
+ * declare(ticks=1) {
+ * // some statements
+ * }
+ * ```
+ * @constant {String} MODE_BLOCK
+ */
+Declare.MODE_BLOCK = "block";
+
+/**
+ * The node is declared as a simple statement. In order to make things simpler
+ * children of the node are automatically collected until the next
+ * declare statement.
+ * ```php
+ * <?php
+ * declare(ticks=1);
+ * // some statements
+ * declare(ticks=2);
+ * // some statements
+ * ```
+ * @constant {String} MODE_NONE
+ */
+Declare.MODE_NONE = "none";
+
+module.exports = Declare;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_declaredirective.js.html b/docs/ast_declaredirective.js.html new file mode 100644 index 000000000..2eb62360b --- /dev/null +++ b/docs/ast_declaredirective.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/declaredirective.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/declaredirective.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "declaredirective";
+
+/**
+ * Defines a constant
+ * @constructor DeclareDirective
+ * @extends {Node}
+ * @property {Identifier} name
+ * @property {Node|string|number|boolean|null} value
+ */
+module.exports = Node.extends(KIND, function DeclareDirective(
+  key,
+  value,
+  docs,
+  location
+) {
+  Node.apply(this, [KIND, docs, location]);
+  this.key = key;
+  this.value = value;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_do.js.html b/docs/ast_do.js.html new file mode 100644 index 000000000..6c988e76d --- /dev/null +++ b/docs/ast_do.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/do.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/do.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "do";
+
+/**
+ * Defines a do/while statement
+ * @constructor Do
+ * @extends {Statement}
+ * @property {Expression} test
+ * @property {Statement} body
+ */
+module.exports = Statement.extends(KIND, function Do(
+  test,
+  body,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.test = test;
+  this.body = body;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_echo.js.html b/docs/ast_echo.js.html new file mode 100644 index 000000000..8d1636e4c --- /dev/null +++ b/docs/ast_echo.js.html @@ -0,0 +1,168 @@ + + + + + + + + + + + ast/echo.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/echo.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "echo";
+
+/**
+ * Defines system based call
+ * @constructor Echo
+ * @property {boolean} shortForm
+ * @extends {Statement}
+ */
+module.exports = Statement.extends(KIND, function Echo(
+  expressions,
+  shortForm,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.shortForm = shortForm;
+  this.expressions = expressions;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_empty.js.html b/docs/ast_empty.js.html new file mode 100644 index 000000000..902108e8e --- /dev/null +++ b/docs/ast_empty.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/empty.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/empty.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "empty";
+
+/**
+ * Defines an empty check call
+ * @constructor Empty
+ * @extends {Expression}
+ */
+module.exports = Expression.extends(KIND, function Empty(
+  expression,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.expression = expression;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_encapsed.js.html b/docs/ast_encapsed.js.html new file mode 100644 index 000000000..4f42f9f75 --- /dev/null +++ b/docs/ast_encapsed.js.html @@ -0,0 +1,214 @@ + + + + + + + + + + + ast/encapsed.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/encapsed.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Literal = require("./literal");
+const KIND = "encapsed";
+
+/**
+ * Defines an encapsed string (contains expressions)
+ * @constructor Encapsed
+ * @extends {Literal}
+ * @property {String} type - Defines the type of encapsed string (shell, heredoc, string)
+ * @property {String|Null} label - The heredoc label, defined only when the type is heredoc
+ */
+const Encapsed = Literal.extends(KIND, function Encapsed(
+  value,
+  raw,
+  type,
+  docs,
+  location
+) {
+  Literal.apply(this, [KIND, value, raw, docs, location]);
+  this.type = type;
+});
+
+/**
+ * The node is a double quote string :
+ * ```php
+ * <?php
+ * echo "hello $world";
+ * ```
+ * @constant {String} TYPE_STRING - `string`
+ */
+Encapsed.TYPE_STRING = "string";
+
+/**
+ * The node is a shell execute string :
+ * ```php
+ * <?php
+ * echo `ls -larth $path`;
+ * ```
+ * @constant {String} TYPE_SHELL - `shell`
+ */
+Encapsed.TYPE_SHELL = "shell";
+
+/**
+ * The node is a shell execute string :
+ * ```php
+ * <?php
+ * echo <<<STR
+ *  Hello $world
+ * STR
+ * ;
+ * ```
+ * @constant {String} TYPE_HEREDOC - `heredoc`
+ */
+Encapsed.TYPE_HEREDOC = "heredoc";
+
+/**
+ * The node contains a list of constref / variables / expr :
+ * ```php
+ * <?php
+ * echo $foo->bar_$baz;
+ * ```
+ * @constant {String} TYPE_OFFSET - `offset`
+ */
+Encapsed.TYPE_OFFSET = "offset";
+
+module.exports = Encapsed;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_encapsedpart.js.html b/docs/ast_encapsedpart.js.html new file mode 100644 index 000000000..8cfc3efbf --- /dev/null +++ b/docs/ast_encapsedpart.js.html @@ -0,0 +1,168 @@ + + + + + + + + + + + ast/encapsedpart.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/encapsedpart.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "encapsedpart";
+
+/**
+ * Part of `Encapsed` node
+ * @constructor EncapsedPart
+ * @extends {Expression}
+ * @property {Expression} what
+ */
+module.exports = Expression.extends(KIND, function EncapsedPart(
+  expression,
+  curly,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.expression = expression;
+  this.curly = curly;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_entry.js.html b/docs/ast_entry.js.html new file mode 100644 index 000000000..ba66dc4f5 --- /dev/null +++ b/docs/ast_entry.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/entry.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/entry.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "entry";
+
+/**
+ * An array entry - see [Array](#array)
+ * @constructor Entry
+ * @extends {Expression}
+ * @property {Node|null} key The entry key/offset
+ * @property {Node} value The entry value
+ */
+module.exports = Expression.extends(KIND, function Entry(
+  key,
+  value,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.key = key;
+  this.value = value;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_error.js.html b/docs/ast_error.js.html new file mode 100644 index 000000000..354112078 --- /dev/null +++ b/docs/ast_error.js.html @@ -0,0 +1,175 @@ + + + + + + + + + + + ast/error.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/error.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "error";
+
+/**
+ * Defines an error node (used only on silentMode)
+ * @constructor Error
+ * @extends {Node}
+ * @property {string} message
+ * @property {number} line
+ * @property {number|string} token
+ * @property {string|array} expected
+ */
+module.exports = Node.extends(KIND, function Error(
+  message,
+  token,
+  line,
+  expected,
+  docs,
+  location
+) {
+  Node.apply(this, [KIND, docs, location]);
+  this.message = message;
+  this.token = token;
+  this.line = line;
+  this.expected = expected;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_eval.js.html b/docs/ast_eval.js.html new file mode 100644 index 000000000..88f63d0e3 --- /dev/null +++ b/docs/ast_eval.js.html @@ -0,0 +1,166 @@ + + + + + + + + + + + ast/eval.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/eval.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "eval";
+
+/**
+ * Defines an eval statement
+ * @constructor Eval
+ * @extends {Expression}
+ * @property {Node} source
+ */
+module.exports = Expression.extends(KIND, function Eval(
+  source,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.source = source;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_exit.js.html b/docs/ast_exit.js.html new file mode 100644 index 000000000..f45ba2560 --- /dev/null +++ b/docs/ast_exit.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/exit.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/exit.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "exit";
+
+/**
+ * Defines an exit / die call
+ * @constructor Exit
+ * @extends {Expression}
+ * @property {Node|null} status
+ * @property {Boolean} useDie
+ */
+module.exports = Expression.extends(KIND, function Exit(
+  status,
+  useDie,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.status = status;
+  this.useDie = useDie;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_expression.js.html b/docs/ast_expression.js.html new file mode 100644 index 000000000..45429ce13 --- /dev/null +++ b/docs/ast_expression.js.html @@ -0,0 +1,161 @@ + + + + + + + + + + + ast/expression.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/expression.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "expression";
+
+/**
+ * Any expression node. Since the left-hand side of an assignment may
+ * be any expression in general, an expression can also be a pattern.
+ * @constructor Expression
+ * @extends {Node}
+ */
+module.exports = Node.extends(KIND, function Expression(kind, docs, location) {
+  Node.apply(this, [kind || KIND, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_expressionstatement.js.html b/docs/ast_expressionstatement.js.html new file mode 100644 index 000000000..49780339e --- /dev/null +++ b/docs/ast_expressionstatement.js.html @@ -0,0 +1,166 @@ + + + + + + + + + + + ast/expressionstatement.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/expressionstatement.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "expressionstatement";
+
+/**
+ * Defines an expression based statement
+ * @constructor ExpressionStatement
+ * @extends {Statement}
+ * @property {Expression} expression
+ */
+module.exports = Statement.extends(KIND, function ExpressionStatement(
+  expr,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.expression = expr;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_for.js.html b/docs/ast_for.js.html new file mode 100644 index 000000000..fb2b02e1b --- /dev/null +++ b/docs/ast_for.js.html @@ -0,0 +1,179 @@ + + + + + + + + + + + ast/for.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/for.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "for";
+
+/**
+ * Defines a for iterator
+ * @constructor For
+ * @extends {Statement}
+ * @property {Expression[]} init
+ * @property {Expression[]} test
+ * @property {Expression[]} increment
+ * @property {Statement} body
+ * @property {boolean} shortForm
+ * @see http://php.net/manual/en/control-structures.for.php
+ */
+module.exports = Statement.extends(KIND, function For(
+  init,
+  test,
+  increment,
+  body,
+  shortForm,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.init = init;
+  this.test = test;
+  this.increment = increment;
+  this.shortForm = shortForm;
+  this.body = body;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_foreach.js.html b/docs/ast_foreach.js.html new file mode 100644 index 000000000..e36b91bdf --- /dev/null +++ b/docs/ast_foreach.js.html @@ -0,0 +1,179 @@ + + + + + + + + + + + ast/foreach.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/foreach.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "foreach";
+
+/**
+ * Defines a foreach iterator
+ * @constructor Foreach
+ * @extends {Statement}
+ * @property {Expression} source
+ * @property {Expression|null} key
+ * @property {Expression} value
+ * @property {Statement} body
+ * @property {boolean} shortForm
+ * @see http://php.net/manual/en/control-structures.foreach.php
+ */
+module.exports = Statement.extends(KIND, function Foreach(
+  source,
+  key,
+  value,
+  body,
+  shortForm,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.source = source;
+  this.key = key;
+  this.value = value;
+  this.shortForm = shortForm;
+  this.body = body;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_function.js.html b/docs/ast_function.js.html new file mode 100644 index 000000000..d9577a9e3 --- /dev/null +++ b/docs/ast_function.js.html @@ -0,0 +1,178 @@ + + + + + + + + + + + ast/function.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/function.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Declaration = require("./declaration");
+const KIND = "function";
+
+/**
+ * Defines a classic function
+ * @constructor Function
+ * @extends {Declaration}
+ * @property {Parameter[]} arguments
+ * @property {Identifier} type
+ * @property {boolean} byref
+ * @property {boolean} nullable
+ * @property {Block|null} body
+ */
+module.exports = Declaration.extends(KIND, function _Function(
+  name,
+  args,
+  byref,
+  type,
+  nullable,
+  docs,
+  location
+) {
+  Declaration.apply(this, [KIND, name, docs, location]);
+  this.arguments = args;
+  this.byref = byref;
+  this.type = type;
+  this.nullable = nullable;
+  this.body = null;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_global.js.html b/docs/ast_global.js.html new file mode 100644 index 000000000..cae4bd4c6 --- /dev/null +++ b/docs/ast_global.js.html @@ -0,0 +1,166 @@ + + + + + + + + + + + ast/global.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/global.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "global";
+
+/**
+ * Imports a variable from the global scope
+ * @constructor Global
+ * @extends {Statement}
+ * @property {Variable[]} items
+ */
+module.exports = Statement.extends(KIND, function Global(
+  items,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.items = items;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_goto.js.html b/docs/ast_goto.js.html new file mode 100644 index 000000000..e0f37841a --- /dev/null +++ b/docs/ast_goto.js.html @@ -0,0 +1,163 @@ + + + + + + + + + + + ast/goto.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/goto.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "goto";
+
+/**
+ * Defines goto statement
+ * @constructor Goto
+ * @extends {Statement}
+ * @property {String} label
+ * @see {Label}
+ */
+module.exports = Statement.extends(KIND, function Goto(label, docs, location) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.label = label;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_halt.js.html b/docs/ast_halt.js.html new file mode 100644 index 000000000..3d70c7700 --- /dev/null +++ b/docs/ast_halt.js.html @@ -0,0 +1,163 @@ + + + + + + + + + + + ast/halt.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/halt.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "halt";
+
+/**
+ * Halts the compiler execution
+ * @constructor Halt
+ * @extends {Statement}
+ * @property {String} after - String after the halt statement
+ * @see http://php.net/manual/en/function.halt-compiler.php
+ */
+module.exports = Statement.extends(KIND, function Halt(after, docs, location) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.after = after;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_identifier.js.html b/docs/ast_identifier.js.html new file mode 100644 index 000000000..c2e2ea1d0 --- /dev/null +++ b/docs/ast_identifier.js.html @@ -0,0 +1,168 @@ + + + + + + + + + + + ast/identifier.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/identifier.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "identifier";
+
+/**
+ * Defines an identifier node
+ * @constructor Identifier
+ * @extends {Node}
+ * @property {string} name
+ */
+const Identifier = Node.extends(KIND, function Identifier(
+  name,
+  docs,
+  location
+) {
+  Node.apply(this, [KIND, docs, location]);
+  this.name = name;
+});
+
+module.exports = Identifier;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_if.js.html b/docs/ast_if.js.html new file mode 100644 index 000000000..bd47743e0 --- /dev/null +++ b/docs/ast_if.js.html @@ -0,0 +1,175 @@ + + + + + + + + + + + ast/if.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/if.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "if";
+
+/**
+ * Defines a if statement
+ * @constructor If
+ * @extends {Statement}
+ * @property {Expression} test
+ * @property {Block} body
+ * @property {Block|If|null} alternate
+ * @property {boolean} shortForm
+ */
+module.exports = Statement.extends(KIND, function If(
+  test,
+  body,
+  alternate,
+  shortForm,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.test = test;
+  this.body = body;
+  this.alternate = alternate;
+  this.shortForm = shortForm;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_include.js.html b/docs/ast_include.js.html new file mode 100644 index 000000000..ea6f368ec --- /dev/null +++ b/docs/ast_include.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/include.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/include.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "include";
+
+/**
+ * Defines system include call
+ * @constructor Include
+ * @extends {Expression}
+ * @property {Node} target
+ * @property {boolean} once
+ * @property {boolean} require
+ */
+module.exports = Expression.extends(KIND, function Include(
+  once,
+  require,
+  target,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.once = once;
+  this.require = require;
+  this.target = target;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_inline.js.html b/docs/ast_inline.js.html new file mode 100644 index 000000000..7b7d4f82c --- /dev/null +++ b/docs/ast_inline.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/inline.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/inline.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Literal = require("./literal");
+const KIND = "inline";
+
+/**
+ * Defines inline html output (treated as echo output)
+ * @constructor Inline
+ * @extends {Literal}
+ */
+module.exports = Literal.extends(KIND, function Inline(
+  value,
+  raw,
+  docs,
+  location
+) {
+  Literal.apply(this, [KIND, value, raw, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_interface.js.html b/docs/ast_interface.js.html new file mode 100644 index 000000000..204a5b25f --- /dev/null +++ b/docs/ast_interface.js.html @@ -0,0 +1,170 @@ + + + + + + + + + + + ast/interface.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/interface.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Declaration = require("./declaration");
+const KIND = "interface";
+
+/**
+ * An interface definition
+ * @constructor Interface
+ * @extends {Declaration}
+ * @property {Identifier[]} extends
+ * @property {Declaration[]} body
+ */
+module.exports = Declaration.extends(KIND, function Interface(
+  name,
+  ext,
+  body,
+  docs,
+  location
+) {
+  Declaration.apply(this, [KIND, name, docs, location]);
+  this.extends = ext;
+  this.body = body;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_isset.js.html b/docs/ast_isset.js.html new file mode 100644 index 000000000..da0a66720 --- /dev/null +++ b/docs/ast_isset.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/isset.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/isset.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "isset";
+
+/**
+ * Defines an isset call
+ * @constructor Isset
+ * @extends {Expression}
+ */
+module.exports = Expression.extends(KIND, function Isset(
+  variables,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.variables = variables;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_label.js.html b/docs/ast_label.js.html new file mode 100644 index 000000000..456dc3e36 --- /dev/null +++ b/docs/ast_label.js.html @@ -0,0 +1,162 @@ + + + + + + + + + + + ast/label.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/label.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "label";
+
+/**
+ * A label statement (referenced by goto)
+ * @constructor Label
+ * @extends {Statement}
+ * @property {String} name
+ */
+module.exports = Statement.extends(KIND, function Label(name, docs, location) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.name = name;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_list.js.html b/docs/ast_list.js.html new file mode 100644 index 000000000..174dffc66 --- /dev/null +++ b/docs/ast_list.js.html @@ -0,0 +1,168 @@ + + + + + + + + + + + ast/list.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/list.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "list";
+
+/**
+ * Defines list assignment
+ * @constructor List
+ * @extends {Expression}
+ * @property {boolean} shortForm
+ */
+module.exports = Expression.extends(KIND, function List(
+  items,
+  shortForm,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.items = items;
+  this.shortForm = shortForm;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_literal.js.html b/docs/ast_literal.js.html new file mode 100644 index 000000000..4f1340810 --- /dev/null +++ b/docs/ast_literal.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/literal.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/literal.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "literal";
+
+/**
+ * Defines an array structure
+ * @constructor Literal
+ * @extends {Expression}
+ * @property {string} raw
+ * @property {Node|string|number|boolean|null} value
+ */
+module.exports = Expression.extends(KIND, function Literal(
+  kind,
+  value,
+  raw,
+  docs,
+  location
+) {
+  Expression.apply(this, [kind || KIND, docs, location]);
+  this.value = value;
+  if (raw) {
+    this.raw = raw;
+  }
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_location.js.html b/docs/ast_location.js.html new file mode 100644 index 000000000..3af06641f --- /dev/null +++ b/docs/ast_location.js.html @@ -0,0 +1,163 @@ + + + + + + + + + + + ast/location.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/location.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+/**
+ * Defines the location of the node (with it's source contents as string)
+ * @constructor Location
+ * @property {String|null} source
+ * @property {Position} start
+ * @property {Position} end
+ */
+const Location = function(source, start, end) {
+  this.source = source;
+  this.start = start;
+  this.end = end;
+};
+
+module.exports = Location;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_lookup.js.html b/docs/ast_lookup.js.html new file mode 100644 index 000000000..e73ea5bd5 --- /dev/null +++ b/docs/ast_lookup.js.html @@ -0,0 +1,170 @@ + + + + + + + + + + + ast/lookup.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/lookup.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expr = require("./expression");
+const KIND = "lookup";
+
+/**
+ * Lookup on an offset in the specified object
+ * @constructor Lookup
+ * @extends {Expression}
+ * @property {Expression} what
+ * @property {Expression} offset
+ */
+module.exports = Expr.extends(KIND, function Lookup(
+  kind,
+  what,
+  offset,
+  docs,
+  location
+) {
+  Expr.apply(this, [kind || KIND, docs, location]);
+  this.what = what;
+  this.offset = offset;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_magic.js.html b/docs/ast_magic.js.html new file mode 100644 index 000000000..eba4cbd51 --- /dev/null +++ b/docs/ast_magic.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/magic.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/magic.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Literal = require("./literal");
+const KIND = "magic";
+
+/**
+ * Defines magic constant
+ * @constructor Magic
+ * @extends {Literal}
+ */
+module.exports = Literal.extends(KIND, function Magic(
+  value,
+  raw,
+  docs,
+  location
+) {
+  Literal.apply(this, [KIND, value, raw, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_method.js.html b/docs/ast_method.js.html new file mode 100644 index 000000000..1cbc59129 --- /dev/null +++ b/docs/ast_method.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/method.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/method.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const _Function = require("./function");
+const KIND = "method";
+
+/**
+ * Defines a class/interface/trait method
+ * @constructor Method
+ * @extends {_Function}
+ * @property {boolean} isAbstract
+ * @property {boolean} isFinal
+ * @property {boolean} isStatic
+ * @property {string} visibility
+ */
+module.exports = _Function.extends(KIND, function Method() {
+  _Function.apply(this, arguments);
+  this.kind = KIND;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_namespace.js.html b/docs/ast_namespace.js.html new file mode 100644 index 000000000..3b3d860cf --- /dev/null +++ b/docs/ast_namespace.js.html @@ -0,0 +1,170 @@ + + + + + + + + + + + ast/namespace.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/namespace.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Block = require("./block");
+const KIND = "namespace";
+
+/**
+ * The main program node
+ * @constructor Namespace
+ * @extends {Block}
+ * @property {String} name
+ * @property {Boolean} withBrackets
+ */
+module.exports = Block.extends(KIND, function Namespace(
+  name,
+  children,
+  withBrackets,
+  docs,
+  location
+) {
+  Block.apply(this, [KIND, children, docs, location]);
+  this.name = name;
+  this.withBrackets = withBrackets || false;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_new.js.html b/docs/ast_new.js.html new file mode 100644 index 000000000..20a1ef74b --- /dev/null +++ b/docs/ast_new.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/new.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/new.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "new";
+
+/**
+ * Creates a new instance of the specified class
+ * @constructor New
+ * @extends {Expression}
+ * @property {Identifier|Variable|Class} what
+ * @property {Arguments[]} arguments
+ */
+module.exports = Expression.extends(KIND, function New(
+  what,
+  args,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.what = what;
+  this.arguments = args;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_node.js.html b/docs/ast_node.js.html new file mode 100644 index 000000000..a7afa2d30 --- /dev/null +++ b/docs/ast_node.js.html @@ -0,0 +1,243 @@ + + + + + + + + + + + ast/node.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/node.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+/**
+ * A generic AST node
+ * @constructor Node
+ * @property {Location|null} loc
+ * @property {Comment[]} leadingComments
+ * @property {Comment[]?} trailingComments
+ * @property {String} kind
+ */
+const Node = function Node(kind, docs, location) {
+  this.kind = kind;
+  if (docs) {
+    this.leadingComments = docs;
+  }
+  if (location) {
+    this.loc = location;
+  }
+};
+
+/**
+ * Attach comments to current node
+ * @param {*} docs
+ */
+Node.prototype.setTrailingComments = function(docs) {
+  this.trailingComments = docs;
+};
+
+/**
+ * Destroying an unused node
+ */
+Node.prototype.destroy = function(node) {
+  if (!node) {
+    throw new Error(
+      "Node already initialized, you must swap with another node"
+    );
+  }
+  if (this.leadingComments) {
+    if (node.leadingComments) {
+      node.leadingComments = Array.concat(
+        this.leadingComments,
+        node.leadingComments
+      );
+    } else {
+      node.leadingComments = this.leadingComments;
+    }
+  }
+  if (this.trailingComments) {
+    if (node.trailingComments) {
+      node.trailingComments = Array.concat(
+        this.trailingComments,
+        node.trailingComments
+      );
+    } else {
+      node.trailingComments = this.trailingComments;
+    }
+  }
+  return node;
+};
+
+/**
+ * Includes current token position of the parser
+ * @param {*} parser
+ */
+Node.prototype.includeToken = function(parser) {
+  if (this.loc) {
+    if (this.loc.end) {
+      this.loc.end.line = parser.lexer.yylloc.last_line;
+      this.loc.end.column = parser.lexer.yylloc.last_column;
+      this.loc.end.offset = parser.lexer.offset;
+    }
+    if (parser.ast.withSource) {
+      this.loc.source = parser.lexer._input.substring(
+        this.loc.start.offset,
+        parser.lexer.offset
+      );
+    }
+  }
+  return this;
+};
+
+/**
+ * Helper for extending the Node class
+ * @param {String} type
+ * @param {Function} constructor
+ * @return {Function}
+ */
+Node.extends = function(type, constructor) {
+  constructor.prototype = Object.create(this.prototype);
+  constructor.extends = this.extends;
+  constructor.prototype.constructor = constructor;
+  constructor.kind = type;
+  return constructor;
+};
+
+module.exports = Node;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_noop.js.html b/docs/ast_noop.js.html new file mode 100644 index 000000000..e8b23353a --- /dev/null +++ b/docs/ast_noop.js.html @@ -0,0 +1,161 @@ + + + + + + + + + + + ast/noop.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/noop.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "noop";
+
+/**
+ * Ignore this node, it implies a no operation block, for example :
+ * [$foo, $bar, /* here a noop node * /]
+ * @constructor Noop
+ * @extends {Node}
+ */
+module.exports = Node.extends(KIND, function Noop(docs, location) {
+  Node.apply(this, [KIND, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_nowdoc.js.html b/docs/ast_nowdoc.js.html new file mode 100644 index 000000000..4642fa08e --- /dev/null +++ b/docs/ast_nowdoc.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/nowdoc.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/nowdoc.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Literal = require("./literal");
+const KIND = "nowdoc";
+
+/**
+ * Defines a nowdoc string
+ * @constructor NowDoc
+ * @extends {Literal}
+ * @property {String} label
+ * @property {String} raw
+ * @property {Boolean} quote
+ */
+module.exports = Literal.extends(KIND, function Nowdoc(
+  value,
+  raw,
+  label,
+  quote,
+  docs,
+  location
+) {
+  Literal.apply(this, [KIND, value, raw, docs, location]);
+  this.label = label;
+  this.quote = quote;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_number.js.html b/docs/ast_number.js.html new file mode 100644 index 000000000..df0b1b750 --- /dev/null +++ b/docs/ast_number.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/number.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/number.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Literal = require("./literal");
+const KIND = "number";
+
+/**
+ * Defines a numeric value
+ * @constructor Number
+ * @extends {Literal}
+ */
+module.exports = Literal.extends(KIND, function Number(
+  value,
+  raw,
+  docs,
+  location
+) {
+  Literal.apply(this, [KIND, value, raw, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_offsetlookup.js.html b/docs/ast_offsetlookup.js.html new file mode 100644 index 000000000..a2c3a55f9 --- /dev/null +++ b/docs/ast_offsetlookup.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/offsetlookup.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/offsetlookup.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Lookup = require("./lookup");
+const KIND = "offsetlookup";
+
+/**
+ * Lookup on an offset in an array
+ * @constructor OffsetLookup
+ * @extends {Lookup}
+ */
+module.exports = Lookup.extends(KIND, function OffsetLookup(
+  what,
+  offset,
+  docs,
+  location
+) {
+  Lookup.apply(this, [KIND, what, offset, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_operation.js.html b/docs/ast_operation.js.html new file mode 100644 index 000000000..ce31b29e0 --- /dev/null +++ b/docs/ast_operation.js.html @@ -0,0 +1,160 @@ + + + + + + + + + + + ast/operation.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/operation.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expr = require("./expression");
+const KIND = "operation";
+
+/**
+ * Defines binary operations
+ * @constructor Operation
+ * @extends {Expression}
+ */
+module.exports = Expr.extends(KIND, function Operation(kind, docs, location) {
+  Expr.apply(this, [kind || KIND, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_parameter.js.html b/docs/ast_parameter.js.html new file mode 100644 index 000000000..995be27b3 --- /dev/null +++ b/docs/ast_parameter.js.html @@ -0,0 +1,179 @@ + + + + + + + + + + + ast/parameter.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/parameter.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Declaration = require("./declaration");
+const KIND = "parameter";
+
+/**
+ * Defines a function parameter
+ * @constructor Parameter
+ * @extends {Declaration}
+ * @property {Identifier|null} type
+ * @property {Node|null} value
+ * @property {boolean} byref
+ * @property {boolean} variadic
+ * @property {boolean} nullable
+ */
+module.exports = Declaration.extends(KIND, function Parameter(
+  name,
+  type,
+  value,
+  isRef,
+  isVariadic,
+  nullable,
+  docs,
+  location
+) {
+  Declaration.apply(this, [KIND, name, docs, location]);
+  this.value = value;
+  this.type = type;
+  this.byref = isRef;
+  this.variadic = isVariadic;
+  this.nullable = nullable;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_parenthesis.js.html b/docs/ast_parenthesis.js.html new file mode 100644 index 000000000..b50e56ebd --- /dev/null +++ b/docs/ast_parenthesis.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/parenthesis.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/parenthesis.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Operation = require("./operation");
+const KIND = "parenthesis";
+
+/**
+ * Parenthesis encapsulation `(... expr ...)`
+ * @constructor Parenthesis
+ * @extends {Operation}
+ * @property {Expression} inner
+ */
+const Parenthesis = Operation.extends(function Parenthesis(
+  inner,
+  docs,
+  location
+) {
+  Operation.apply(this, [KIND, docs, location]);
+  this.inner = inner;
+});
+
+module.exports = Parenthesis;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_parentreference.js.html b/docs/ast_parentreference.js.html new file mode 100644 index 000000000..393910870 --- /dev/null +++ b/docs/ast_parentreference.js.html @@ -0,0 +1,166 @@ + + + + + + + + + + + ast/parentreference.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/parentreference.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Reference = require("./reference");
+const KIND = "parentreference";
+
+/**
+ * Defines a class reference node
+ * @constructor ParentReference
+ * @extends {Reference}
+ */
+const ParentReference = Reference.extends(KIND, function ParentReference(
+  raw,
+  docs,
+  location
+) {
+  Reference.apply(this, [KIND, docs, location]);
+  this.raw = raw;
+});
+module.exports = ParentReference;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_position.js.html b/docs/ast_position.js.html new file mode 100644 index 000000000..6649d4dfc --- /dev/null +++ b/docs/ast_position.js.html @@ -0,0 +1,163 @@ + + + + + + + + + + + ast/position.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/position.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+/**
+ * Each Position object consists of a line number (1-indexed) and a column number (0-indexed):
+ * @constructor Position
+ * @property {Number} line
+ * @property {Number} column
+ * @property {Number} offset
+ */
+const Position = function(line, column, offset) {
+  this.line = line;
+  this.column = column;
+  this.offset = offset;
+};
+
+module.exports = Position;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_post.js.html b/docs/ast_post.js.html new file mode 100644 index 000000000..6d40b51e4 --- /dev/null +++ b/docs/ast_post.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/post.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/post.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Operation = require("./operation");
+const KIND = "post";
+
+/**
+ * Defines a post operation `$i++` or `$i--`
+ * @constructor Post
+ * @extends {Operation}
+ * @property {String} type
+ * @property {Variable} what
+ */
+module.exports = Operation.extends(KIND, function Post(
+  type,
+  what,
+  docs,
+  location
+) {
+  Operation.apply(this, [KIND, docs, location]);
+  this.type = type;
+  this.what = what;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_pre.js.html b/docs/ast_pre.js.html new file mode 100644 index 000000000..f81dbb3da --- /dev/null +++ b/docs/ast_pre.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/pre.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/pre.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Operation = require("./operation");
+const KIND = "pre";
+
+/**
+ * Defines a pre operation `++$i` or `--$i`
+ * @constructor Pre
+ * @extends {Operation}
+ * @property {String} type
+ * @property {Variable} what
+ */
+module.exports = Operation.extends(KIND, function Pre(
+  type,
+  what,
+  docs,
+  location
+) {
+  Operation.apply(this, [KIND, docs, location]);
+  this.type = type;
+  this.what = what;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_print.js.html b/docs/ast_print.js.html new file mode 100644 index 000000000..49991bef6 --- /dev/null +++ b/docs/ast_print.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/print.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/print.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "print";
+
+/**
+ * Outputs
+ * @constructor Print
+ * @extends {Expression}
+ */
+module.exports = Expression.extends(KIND, function Print(
+  expression,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.expression = expression;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_program.js.html b/docs/ast_program.js.html new file mode 100644 index 000000000..471a95b0e --- /dev/null +++ b/docs/ast_program.js.html @@ -0,0 +1,177 @@ + + + + + + + + + + + ast/program.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/program.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Block = require("./block");
+const KIND = "program";
+
+/**
+ * The main program node
+ * @constructor Program
+ * @extends {Block}
+ * @property {Error[]} errors
+ * @property {Doc[]?} comments
+ * @property {String[]?} tokens
+ */
+module.exports = Block.extends(KIND, function Program(
+  children,
+  errors,
+  comments,
+  tokens,
+  docs,
+  location
+) {
+  Block.apply(this, [KIND, children, docs, location]);
+  this.errors = errors;
+  if (comments) {
+    this.comments = comments;
+  }
+  if (tokens) {
+    this.tokens = tokens;
+  }
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_property.js.html b/docs/ast_property.js.html new file mode 100644 index 000000000..a2a5ed60c --- /dev/null +++ b/docs/ast_property.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/property.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/property.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "property";
+
+/**
+ * Defines a class property
+ * @constructor Property
+ * @extends {Statement}
+ * @property {string} name
+ * @property {Node|null} value
+ */
+module.exports = Statement.extends(KIND, function Property(
+  name,
+  value,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.name = name;
+  this.value = value;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_propertylookup.js.html b/docs/ast_propertylookup.js.html new file mode 100644 index 000000000..f58353b38 --- /dev/null +++ b/docs/ast_propertylookup.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/propertylookup.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/propertylookup.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Lookup = require("./lookup");
+const KIND = "propertylookup";
+
+/**
+ * Lookup to an object property
+ * @constructor PropertyLookup
+ * @extends {Lookup}
+ */
+module.exports = Lookup.extends(KIND, function PropertyLookup(
+  what,
+  offset,
+  docs,
+  location
+) {
+  Lookup.apply(this, [KIND, what, offset, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_propertystatement.js.html b/docs/ast_propertystatement.js.html new file mode 100644 index 000000000..09f814f68 --- /dev/null +++ b/docs/ast_propertystatement.js.html @@ -0,0 +1,197 @@ + + + + + + + + + + + ast/propertystatement.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/propertystatement.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "propertystatement";
+
+const IS_UNDEFINED = "";
+const IS_PUBLIC = "public";
+const IS_PROTECTED = "protected";
+const IS_PRIVATE = "private";
+
+/**
+ * Declares a properties into the current scope
+ * @constructor PropertyStatement
+ * @extends {Statement}
+ * @property {Property[]} properties
+ */
+const PropertyStatement = Statement.extends(KIND, function PropertyStatement(
+  kind,
+  properties,
+  flags,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.properties = properties;
+  this.parseFlags(flags);
+});
+
+/**
+ * Generic flags parser
+ * @param {Integer[]} flags
+ * @return {void}
+ */
+PropertyStatement.prototype.parseFlags = function(flags) {
+  if (flags[0] === -1) {
+    this.visibility = IS_UNDEFINED;
+  } else if (flags[0] === null) {
+    this.visibility = null;
+  } else if (flags[0] === 0) {
+    this.visibility = IS_PUBLIC;
+  } else if (flags[0] === 1) {
+    this.visibility = IS_PROTECTED;
+  } else if (flags[0] === 2) {
+    this.visibility = IS_PRIVATE;
+  }
+
+  this.isStatic = flags[1] === 1;
+};
+
+module.exports = PropertyStatement;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_reference.js.html b/docs/ast_reference.js.html new file mode 100644 index 000000000..927520861 --- /dev/null +++ b/docs/ast_reference.js.html @@ -0,0 +1,162 @@ + + + + + + + + + + + ast/reference.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/reference.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "reference";
+
+/**
+ * Defines a reference node
+ * @constructor Reference
+ * @extends {Node}
+ */
+const Reference = Node.extends(KIND, function Reference(kind, docs, location) {
+  Node.apply(this, [kind || KIND, docs, location]);
+});
+
+module.exports = Reference;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_retif.js.html b/docs/ast_retif.js.html new file mode 100644 index 000000000..410f28b2b --- /dev/null +++ b/docs/ast_retif.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/retif.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/retif.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "retif";
+
+/**
+ * Defines a short if statement that returns a value
+ * @constructor RetIf
+ * @extends {Expression}
+ * @property {Expression} test
+ * @property {Expression} trueExpr
+ * @property {Expression} falseExpr
+ */
+module.exports = Expression.extends(KIND, function RetIf(
+  test,
+  trueExpr,
+  falseExpr,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.test = test;
+  this.trueExpr = trueExpr;
+  this.falseExpr = falseExpr;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_return.js.html b/docs/ast_return.js.html new file mode 100644 index 000000000..d19859c8d --- /dev/null +++ b/docs/ast_return.js.html @@ -0,0 +1,162 @@ + + + + + + + + + + + ast/return.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/return.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "return";
+
+/**
+ * A continue statement
+ * @constructor Return
+ * @extends {Statement}
+ * @property {Expression|null} expr
+ */
+module.exports = Statement.extends(KIND, function Return(expr, docs, location) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.expr = expr;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_selfreference.js.html b/docs/ast_selfreference.js.html new file mode 100644 index 000000000..5d37a64ae --- /dev/null +++ b/docs/ast_selfreference.js.html @@ -0,0 +1,166 @@ + + + + + + + + + + + ast/selfreference.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/selfreference.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Reference = require("./reference");
+const KIND = "selfreference";
+
+/**
+ * Defines a class reference node
+ * @constructor SelfReference
+ * @extends {Reference}
+ */
+const SelfReference = Reference.extends(KIND, function SelfReference(
+  raw,
+  docs,
+  location
+) {
+  Reference.apply(this, [KIND, docs, location]);
+  this.raw = raw;
+});
+module.exports = SelfReference;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_silent.js.html b/docs/ast_silent.js.html new file mode 100644 index 000000000..2f59f8bc0 --- /dev/null +++ b/docs/ast_silent.js.html @@ -0,0 +1,166 @@ + + + + + + + + + + + ast/silent.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/silent.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "silent";
+
+/**
+ * Avoids to show/log warnings & notices from the inner expression
+ * @constructor Silent
+ * @extends {Expression}
+ * @property {Expression} expr
+ */
+module.exports = Expression.extends(KIND, function Silent(
+  expr,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.expr = expr;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_statement.js.html b/docs/ast_statement.js.html new file mode 100644 index 000000000..39eec6e81 --- /dev/null +++ b/docs/ast_statement.js.html @@ -0,0 +1,160 @@ + + + + + + + + + + + ast/statement.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/statement.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "statement";
+
+/**
+ * Any statement.
+ * @constructor Statement
+ * @extends {Node}
+ */
+module.exports = Node.extends(KIND, function Statement(kind, docs, location) {
+  Node.apply(this, [kind || KIND, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_static.js.html b/docs/ast_static.js.html new file mode 100644 index 000000000..6208ef46b --- /dev/null +++ b/docs/ast_static.js.html @@ -0,0 +1,166 @@ + + + + + + + + + + + ast/static.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/static.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "static";
+
+/**
+ * Declares a static variable into the current scope
+ * @constructor Static
+ * @extends {Statement}
+ * @property {StaticVariable[]} variables
+ */
+module.exports = Statement.extends(KIND, function Static(
+  variables,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.variables = variables;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_staticlookup.js.html b/docs/ast_staticlookup.js.html new file mode 100644 index 000000000..fad639213 --- /dev/null +++ b/docs/ast_staticlookup.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/staticlookup.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/staticlookup.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Lookup = require("./lookup");
+const KIND = "staticlookup";
+
+/**
+ * Lookup to a static property
+ * @constructor StaticLookup
+ * @extends {Lookup}
+ */
+module.exports = Lookup.extends(KIND, function StaticLookup(
+  what,
+  offset,
+  docs,
+  location
+) {
+  Lookup.apply(this, [KIND, what, offset, docs, location]);
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_staticreference.js.html b/docs/ast_staticreference.js.html new file mode 100644 index 000000000..1649735e6 --- /dev/null +++ b/docs/ast_staticreference.js.html @@ -0,0 +1,166 @@ + + + + + + + + + + + ast/staticreference.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/staticreference.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Reference = require("./reference");
+const KIND = "staticreference";
+
+/**
+ * Defines a class reference node
+ * @constructor StaticReference
+ * @extends {Reference}
+ */
+const StaticReference = Reference.extends(KIND, function StaticReference(
+  raw,
+  docs,
+  location
+) {
+  Reference.apply(this, [KIND, docs, location]);
+  this.raw = raw;
+});
+module.exports = StaticReference;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_staticvariable.js.html b/docs/ast_staticvariable.js.html new file mode 100644 index 000000000..260473866 --- /dev/null +++ b/docs/ast_staticvariable.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/staticvariable.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/staticvariable.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "staticvariable";
+
+/**
+ * Defines a constant
+ * @constructor StaticVariable
+ * @extends {Node}
+ * @property {Variable} variable
+ * @property {Node|string|number|boolean|null} defaultValue
+ */
+module.exports = Node.extends(KIND, function StaticVariable(
+  variable,
+  defaultValue,
+  docs,
+  location
+) {
+  Node.apply(this, [KIND, docs, location]);
+  this.variable = variable;
+  this.defaultValue = defaultValue;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_string.js.html b/docs/ast_string.js.html new file mode 100644 index 000000000..dd1460716 --- /dev/null +++ b/docs/ast_string.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/string.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/string.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Literal = require("./literal");
+const KIND = "string";
+
+/**
+ * Defines a string (simple ou double quoted) - chars are already escaped
+ * @constructor String
+ * @extends {Literal}
+ * @property {boolean} unicode
+ * @property {boolean} isDoubleQuote
+ * @see {Encapsed}
+ */
+module.exports = Literal.extends(KIND, function String(
+  isDoubleQuote,
+  value,
+  unicode,
+  raw,
+  docs,
+  location
+) {
+  Literal.apply(this, [KIND, value, raw, docs, location]);
+  this.unicode = unicode;
+  this.isDoubleQuote = isDoubleQuote;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_switch.js.html b/docs/ast_switch.js.html new file mode 100644 index 000000000..07fb7741f --- /dev/null +++ b/docs/ast_switch.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/switch.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/switch.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "switch";
+
+/**
+ * Defines a switch statement
+ * @constructor Switch
+ * @extends {Statement}
+ * @property {Expression} test
+ * @property {Block} body
+ * @property {boolean} shortForm
+ */
+module.exports = Statement.extends(KIND, function Switch(
+  test,
+  body,
+  shortForm,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.test = test;
+  this.body = body;
+  this.shortForm = shortForm;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_sys.js.html b/docs/ast_sys.js.html new file mode 100644 index 000000000..a1b9cb200 --- /dev/null +++ b/docs/ast_sys.js.html @@ -0,0 +1,164 @@ + + + + + + + + + + + ast/sys.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/sys.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "sys";
+
+/**
+ * Defines system based call
+ * @constructor Sys
+ * @extends {Statement}
+ * @property {Node[]} arguments
+ */
+module.exports = Statement.extends(KIND, function Sys(
+  kind,
+  args,
+  docs,
+  location
+) {
+  Statement.apply(this, [kind || KIND, docs, location]);
+  this.arguments = args;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_throw.js.html b/docs/ast_throw.js.html new file mode 100644 index 000000000..1b3b52ebb --- /dev/null +++ b/docs/ast_throw.js.html @@ -0,0 +1,162 @@ + + + + + + + + + + + ast/throw.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/throw.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "throw";
+
+/**
+ * Defines a throw statement
+ * @constructor Throw
+ * @extends {Statement}
+ * @property {Expression} what
+ */
+module.exports = Statement.extends(KIND, function Throw(what, docs, location) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.what = what;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_trait.js.html b/docs/ast_trait.js.html new file mode 100644 index 000000000..c11f9e5cf --- /dev/null +++ b/docs/ast_trait.js.html @@ -0,0 +1,167 @@ + + + + + + + + + + + ast/trait.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/trait.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Declaration = require("./declaration");
+const KIND = "trait";
+
+/**
+ * A trait definition
+ * @constructor Trait
+ * @extends {Declaration}
+ * @property {Declaration[]} body
+ */
+module.exports = Declaration.extends(KIND, function Trait(
+  name,
+  body,
+  docs,
+  location
+) {
+  Declaration.apply(this, [KIND, name, docs, location]);
+  this.body = body;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_traitalias.js.html b/docs/ast_traitalias.js.html new file mode 100644 index 000000000..88b72eba9 --- /dev/null +++ b/docs/ast_traitalias.js.html @@ -0,0 +1,189 @@ + + + + + + + + + + + ast/traitalias.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/traitalias.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "traitalias";
+
+const IS_UNDEFINED = "";
+const IS_PUBLIC = "public";
+const IS_PROTECTED = "protected";
+const IS_PRIVATE = "private";
+
+/**
+ * Defines a trait alias
+ * @constructor TraitAlias
+ * @extends {Node}
+ * @property {Identifier|null} trait
+ * @property {Identifier} method
+ * @property {Identifier|null} as
+ * @property {string|null} visibility
+ */
+module.exports = Node.extends(KIND, function TraitAlias(
+  trait,
+  method,
+  as,
+  flags,
+  docs,
+  location
+) {
+  Node.apply(this, [KIND, docs, location]);
+  this.trait = trait;
+  this.method = method;
+  this.as = as;
+  this.visibility = IS_UNDEFINED;
+  if (flags) {
+    if (flags[0] === 0) {
+      this.visibility = IS_PUBLIC;
+    } else if (flags[0] === 1) {
+      this.visibility = IS_PROTECTED;
+    } else if (flags[0] === 2) {
+      this.visibility = IS_PRIVATE;
+    }
+  }
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_traitprecedence.js.html b/docs/ast_traitprecedence.js.html new file mode 100644 index 000000000..2a58f0ef8 --- /dev/null +++ b/docs/ast_traitprecedence.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/traitprecedence.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/traitprecedence.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "traitprecedence";
+
+/**
+ * Defines a trait alias
+ * @constructor TraitPrecedence
+ * @extends {Node}
+ * @property {Identifier|null} trait
+ * @property {Identifier} method
+ * @property {Identifier[]} instead
+ */
+module.exports = Node.extends(KIND, function TraitPrecedence(
+  trait,
+  method,
+  instead,
+  docs,
+  location
+) {
+  Node.apply(this, [KIND, docs, location]);
+  this.trait = trait;
+  this.method = method;
+  this.instead = instead;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_traituse.js.html b/docs/ast_traituse.js.html new file mode 100644 index 000000000..c54c00c1b --- /dev/null +++ b/docs/ast_traituse.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/traituse.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/traituse.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Node = require("./node");
+const KIND = "traituse";
+
+/**
+ * Defines a trait usage
+ * @constructor TraitUse
+ * @extends {Node}
+ * @property {Identifier[]} traits
+ * @property {Node[]|null} adaptations
+ */
+module.exports = Node.extends(KIND, function TraitUse(
+  traits,
+  adaptations,
+  docs,
+  location
+) {
+  Node.apply(this, [KIND, docs, location]);
+  this.traits = traits;
+  this.adaptations = adaptations;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_try.js.html b/docs/ast_try.js.html new file mode 100644 index 000000000..42537f483 --- /dev/null +++ b/docs/ast_try.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/try.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/try.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "try";
+
+/**
+ * Defines a try statement
+ * @constructor Try
+ * @extends {Statement}
+ * @property {Block} body
+ * @property {Catch[]} catches
+ * @property {Block} always
+ */
+module.exports = Statement.extends(KIND, function Try(
+  body,
+  catches,
+  always,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.body = body;
+  this.catches = catches;
+  this.always = always;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_typereference.js.html b/docs/ast_typereference.js.html new file mode 100644 index 000000000..9dce07b6a --- /dev/null +++ b/docs/ast_typereference.js.html @@ -0,0 +1,182 @@ + + + + + + + + + + + ast/typereference.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/typereference.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Reference = require("./reference");
+const KIND = "typereference";
+
+/**
+ * Defines a class reference node
+ * @constructor TypeReference
+ * @extends {Reference}
+ * @property {string} name
+ */
+const TypeReference = Reference.extends(KIND, function TypeReference(
+  name,
+  raw,
+  docs,
+  location
+) {
+  Reference.apply(this, [KIND, docs, location]);
+  this.name = name;
+  this.raw = raw;
+});
+
+TypeReference.types = [
+  "int",
+  "float",
+  "string",
+  "bool",
+  "object",
+  "array",
+  "callable",
+  "iterable",
+  "void"
+];
+
+module.exports = TypeReference;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_unary.js.html b/docs/ast_unary.js.html new file mode 100644 index 000000000..701419d91 --- /dev/null +++ b/docs/ast_unary.js.html @@ -0,0 +1,169 @@ + + + + + + + + + + + ast/unary.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/unary.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Operation = require("./operation");
+const KIND = "unary";
+
+/**
+ * Unary operations
+ * @constructor Unary
+ * @extends {Operation}
+ * @property {String} type
+ * @property {Expression} what
+ */
+module.exports = Operation.extends(KIND, function Unary(
+  type,
+  what,
+  docs,
+  location
+) {
+  Operation.apply(this, [KIND, docs, location]);
+  this.type = type;
+  this.what = what;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_unset.js.html b/docs/ast_unset.js.html new file mode 100644 index 000000000..952bfb7a9 --- /dev/null +++ b/docs/ast_unset.js.html @@ -0,0 +1,165 @@ + + + + + + + + + + + ast/unset.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/unset.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "unset";
+
+/**
+ * Deletes references to a list of variables
+ * @constructor Unset
+ * @extends {Statement}
+ */
+module.exports = Statement.extends(KIND, function Unset(
+  variables,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.variables = variables;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_usegroup.js.html b/docs/ast_usegroup.js.html new file mode 100644 index 000000000..3140cf3f9 --- /dev/null +++ b/docs/ast_usegroup.js.html @@ -0,0 +1,174 @@ + + + + + + + + + + + ast/usegroup.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/usegroup.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "usegroup";
+
+/**
+ * Defines a use statement (with a list of use items)
+ * @constructor UseGroup
+ * @extends {Statement}
+ * @property {String|null} name
+ * @property {String|null} type - Possible value : function, const
+ * @property {UseItem[]} item
+ * @see {Namespace}
+ * @see http://php.net/manual/en/language.namespaces.importing.php
+ */
+module.exports = Statement.extends(KIND, function UseGroup(
+  name,
+  type,
+  items,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.name = name;
+  this.type = type;
+  this.items = items;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_useitem.js.html b/docs/ast_useitem.js.html new file mode 100644 index 000000000..6db8920ad --- /dev/null +++ b/docs/ast_useitem.js.html @@ -0,0 +1,187 @@ + + + + + + + + + + + ast/useitem.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/useitem.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "useitem";
+
+/**
+ * Defines a use statement (from namespace)
+ * @constructor UseItem
+ * @extends {Statement}
+ * @property {String} name
+ * @property {String|null} type - Possible value : function, const
+ * @property {Identifier|null} alias
+ * @see {Namespace}
+ * @see http://php.net/manual/en/language.namespaces.importing.php
+ */
+const UseItem = Statement.extends(KIND, function UseItem(
+  name,
+  alias,
+  type,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.name = name;
+  this.alias = alias;
+  this.type = type;
+});
+
+/**
+ * Importing a constant
+ * @constant {String} TYPE_CONST
+ */
+UseItem.TYPE_CONST = "const";
+/**
+ * Importing a function
+ * @constant {String} TYPE_FUNC
+ */
+UseItem.TYPE_FUNCTION = "function";
+
+module.exports = UseItem;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_variable.js.html b/docs/ast_variable.js.html new file mode 100644 index 000000000..3824b05f5 --- /dev/null +++ b/docs/ast_variable.js.html @@ -0,0 +1,183 @@ + + + + + + + + + + + ast/variable.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/variable.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "variable";
+
+/**
+ * Any expression node. Since the left-hand side of an assignment may
+ * be any expression in general, an expression can also be a pattern.
+ * @constructor Variable
+ * @extends {Expression}
+ * @example
+ * // PHP code :
+ * &$foo
+ * // AST output
+ * {
+ *  "kind": "variable",
+ *  "name": "foo",
+ *  "byref": true,
+ *  "curly": false
+ * }
+ * @property {String|Node} name The variable name (can be a complex expression when the name is resolved dynamically)
+ * @property {boolean} byref Indicate if the variable reference is used, ex `&$foo`
+ * @property {boolean} curly Indicate if the name is defined between curlies, ex `${foo}`
+ */
+module.exports = Expression.extends(KIND, function Variable(
+  name,
+  byref,
+  curly,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.name = name;
+  this.byref = byref || false;
+  this.curly = curly || false;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_variadic.js.html b/docs/ast_variadic.js.html new file mode 100644 index 000000000..3086bf4c3 --- /dev/null +++ b/docs/ast_variadic.js.html @@ -0,0 +1,167 @@ + + + + + + + + + + + ast/variadic.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/variadic.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "variadic";
+
+/**
+ * Introduce a list of items into the arguments of the call
+ * @constructor variadic
+ * @extends {Expression}
+ * @property {Array|Expression} what
+ * @see https://wiki.php.net/rfc/argument_unpacking
+ */
+module.exports = Expression.extends(KIND, function variadic(
+  what,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.what = what;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_while.js.html b/docs/ast_while.js.html new file mode 100644 index 000000000..2ebc334c0 --- /dev/null +++ b/docs/ast_while.js.html @@ -0,0 +1,172 @@ + + + + + + + + + + + ast/while.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/while.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Statement = require("./statement");
+const KIND = "while";
+
+/**
+ * Defines a while statement
+ * @constructor While
+ * @extends {Statement}
+ * @property {Expression} test
+ * @property {Statement} body
+ * @property {boolean} shortForm
+ */
+module.exports = Statement.extends(KIND, function While(
+  test,
+  body,
+  shortForm,
+  docs,
+  location
+) {
+  Statement.apply(this, [KIND, docs, location]);
+  this.test = test;
+  this.body = body;
+  this.shortForm = shortForm;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_yield.js.html b/docs/ast_yield.js.html new file mode 100644 index 000000000..c8a604ba3 --- /dev/null +++ b/docs/ast_yield.js.html @@ -0,0 +1,170 @@ + + + + + + + + + + + ast/yield.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/yield.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "yield";
+
+/**
+ * Defines a yield generator statement
+ * @constructor Yield
+ * @extends {Expression}
+ * @property {Expression|Null} value
+ * @property {Expression|Null} key
+ * @see http://php.net/manual/en/language.generators.syntax.php
+ */
+module.exports = Expression.extends(KIND, function Yield(
+  value,
+  key,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.value = value;
+  this.key = key;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/ast_yieldfrom.js.html b/docs/ast_yieldfrom.js.html new file mode 100644 index 000000000..a37fab448 --- /dev/null +++ b/docs/ast_yieldfrom.js.html @@ -0,0 +1,167 @@ + + + + + + + + + + + ast/yieldfrom.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ ast/yieldfrom.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const Expression = require("./expression");
+const KIND = "yieldfrom";
+
+/**
+ * Defines a yield from generator statement
+ * @constructor YieldFrom
+ * @extends {Expression}
+ * @property {Expression} value
+ * @see http://php.net/manual/en/language.generators.syntax.php
+ */
+module.exports = Expression.extends(KIND, function YieldFrom(
+  value,
+  docs,
+  location
+) {
+  Expression.apply(this, [KIND, docs, location]);
+  this.value = value;
+});
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/engine.html b/docs/engine.html new file mode 100644 index 000000000..f21572235 --- /dev/null +++ b/docs/engine.html @@ -0,0 +1,989 @@ + + + + + + + + + engine - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ engine +

+ + + + +
+
+ +

+ + engine + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new engine(options) +

+
+ + + + + +
+

Initialise a new parser instance with the specified options

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
options + + + + Object + + + + + + + +

List of options

+ +
+ + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
lexer + + + + Lexer + + + + + + + + +
parser + + + + Parser + + + + + + + + +
ast + + + + AST + + + + + + + + +
tokens + + + + Object + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + +
Tutorials:
+
+ +
+ + + + + +
+ + + + + + + + + + + + + +
+ + + + + +
Example
+ + +
var parser = require('php-parser');
+var instance = new parser({
+  parser: {
+    extractDoc: true,
+    suppressErrors: true,
+    php7: true
+  },
+  ast: {
+    withPositions: true
+  },
+  lexer: {
+    short_tags: true,
+    asp_tags: true
+  }
+});
+
+var evalAST = instance.parseEval('some php code');
+var codeAST = instance.parseCode('<?php some php code', 'foo.php');
+var tokens = instance.tokenGetAll('<?php some php code');
+ + +
+ + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ parseCode(buffer, filename) → {Program} +

+
+ + + + + +
+

Function that parse a php code with open/close tags

+

Sample code :

+
<?php $x = 1;
+
+

Usage :

+
var parser = require('php-parser');
+var phpParser = new parser({
+  // some options
+});
+var ast = phpParser.parseCode('...php code...', 'foo.php');
+
+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
buffer + + + + String + + + + + + + +

The code to be parsed

+ +
filename + + + + String + + + + + + + +

Filename

+ +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ parseEval(buffer) → {Program} +

+
+ + + + + +
+

Parse an evaluating mode string (no need to open php tags)

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
buffer + + + + String + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ tokenGetAll(buffer) → {Array.<String>} +

+
+ + + + + +
+

Extract tokens from the specified buffer.

+
+

Note that the output tokens are STRICLY similar to PHP function token_get_all

+
+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
buffer + + + + String + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-Bold-webfont.eot b/docs/fonts/OpenSans-Bold-webfont.eot new file mode 100644 index 000000000..5d20d9163 Binary files /dev/null and b/docs/fonts/OpenSans-Bold-webfont.eot differ diff --git a/docs/fonts/OpenSans-Bold-webfont.svg b/docs/fonts/OpenSans-Bold-webfont.svg new file mode 100644 index 000000000..3ed7be4bc --- /dev/null +++ b/docs/fonts/OpenSans-Bold-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-Bold-webfont.woff b/docs/fonts/OpenSans-Bold-webfont.woff new file mode 100644 index 000000000..1205787b0 Binary files /dev/null and b/docs/fonts/OpenSans-Bold-webfont.woff differ diff --git a/docs/fonts/OpenSans-BoldItalic-webfont.eot b/docs/fonts/OpenSans-BoldItalic-webfont.eot new file mode 100644 index 000000000..1f639a15f Binary files /dev/null and b/docs/fonts/OpenSans-BoldItalic-webfont.eot differ diff --git a/docs/fonts/OpenSans-BoldItalic-webfont.svg b/docs/fonts/OpenSans-BoldItalic-webfont.svg new file mode 100644 index 000000000..6a2607b9d --- /dev/null +++ b/docs/fonts/OpenSans-BoldItalic-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-BoldItalic-webfont.woff b/docs/fonts/OpenSans-BoldItalic-webfont.woff new file mode 100644 index 000000000..ed760c062 Binary files /dev/null and b/docs/fonts/OpenSans-BoldItalic-webfont.woff differ diff --git a/docs/fonts/OpenSans-Italic-webfont.eot b/docs/fonts/OpenSans-Italic-webfont.eot new file mode 100644 index 000000000..0c8a0ae06 Binary files /dev/null and b/docs/fonts/OpenSans-Italic-webfont.eot differ diff --git a/docs/fonts/OpenSans-Italic-webfont.svg b/docs/fonts/OpenSans-Italic-webfont.svg new file mode 100644 index 000000000..e1075dcc2 --- /dev/null +++ b/docs/fonts/OpenSans-Italic-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-Italic-webfont.woff b/docs/fonts/OpenSans-Italic-webfont.woff new file mode 100644 index 000000000..ff652e643 Binary files /dev/null and b/docs/fonts/OpenSans-Italic-webfont.woff differ diff --git a/docs/fonts/OpenSans-Light-webfont.eot b/docs/fonts/OpenSans-Light-webfont.eot new file mode 100644 index 000000000..14868406a Binary files /dev/null and b/docs/fonts/OpenSans-Light-webfont.eot differ diff --git a/docs/fonts/OpenSans-Light-webfont.svg b/docs/fonts/OpenSans-Light-webfont.svg new file mode 100644 index 000000000..11a472ca8 --- /dev/null +++ b/docs/fonts/OpenSans-Light-webfont.svg @@ -0,0 +1,1831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-Light-webfont.woff b/docs/fonts/OpenSans-Light-webfont.woff new file mode 100644 index 000000000..e78607481 Binary files /dev/null and b/docs/fonts/OpenSans-Light-webfont.woff differ diff --git a/docs/fonts/OpenSans-LightItalic-webfont.eot b/docs/fonts/OpenSans-LightItalic-webfont.eot new file mode 100644 index 000000000..8f445929f Binary files /dev/null and b/docs/fonts/OpenSans-LightItalic-webfont.eot differ diff --git a/docs/fonts/OpenSans-LightItalic-webfont.svg b/docs/fonts/OpenSans-LightItalic-webfont.svg new file mode 100644 index 000000000..431d7e354 --- /dev/null +++ b/docs/fonts/OpenSans-LightItalic-webfont.svg @@ -0,0 +1,1835 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-LightItalic-webfont.woff b/docs/fonts/OpenSans-LightItalic-webfont.woff new file mode 100644 index 000000000..43e8b9e6c Binary files /dev/null and b/docs/fonts/OpenSans-LightItalic-webfont.woff differ diff --git a/docs/fonts/OpenSans-Regular-webfont.eot b/docs/fonts/OpenSans-Regular-webfont.eot new file mode 100644 index 000000000..6bbc3cf58 Binary files /dev/null and b/docs/fonts/OpenSans-Regular-webfont.eot differ diff --git a/docs/fonts/OpenSans-Regular-webfont.svg b/docs/fonts/OpenSans-Regular-webfont.svg new file mode 100644 index 000000000..25a395234 --- /dev/null +++ b/docs/fonts/OpenSans-Regular-webfont.svg @@ -0,0 +1,1831 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-Regular-webfont.woff b/docs/fonts/OpenSans-Regular-webfont.woff new file mode 100644 index 000000000..e231183dc Binary files /dev/null and b/docs/fonts/OpenSans-Regular-webfont.woff differ diff --git a/docs/fonts/OpenSans-Semibold-webfont.eot b/docs/fonts/OpenSans-Semibold-webfont.eot new file mode 100755 index 000000000..d8375dd0a Binary files /dev/null and b/docs/fonts/OpenSans-Semibold-webfont.eot differ diff --git a/docs/fonts/OpenSans-Semibold-webfont.svg b/docs/fonts/OpenSans-Semibold-webfont.svg new file mode 100755 index 000000000..eec4db8bd --- /dev/null +++ b/docs/fonts/OpenSans-Semibold-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-Semibold-webfont.ttf b/docs/fonts/OpenSans-Semibold-webfont.ttf new file mode 100755 index 000000000..b3290843a Binary files /dev/null and b/docs/fonts/OpenSans-Semibold-webfont.ttf differ diff --git a/docs/fonts/OpenSans-Semibold-webfont.woff b/docs/fonts/OpenSans-Semibold-webfont.woff new file mode 100755 index 000000000..28d6adee0 Binary files /dev/null and b/docs/fonts/OpenSans-Semibold-webfont.woff differ diff --git a/docs/fonts/OpenSans-SemiboldItalic-webfont.eot b/docs/fonts/OpenSans-SemiboldItalic-webfont.eot new file mode 100755 index 000000000..0ab1db22e Binary files /dev/null and b/docs/fonts/OpenSans-SemiboldItalic-webfont.eot differ diff --git a/docs/fonts/OpenSans-SemiboldItalic-webfont.svg b/docs/fonts/OpenSans-SemiboldItalic-webfont.svg new file mode 100755 index 000000000..7166ec1b9 --- /dev/null +++ b/docs/fonts/OpenSans-SemiboldItalic-webfont.svg @@ -0,0 +1,1830 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/OpenSans-SemiboldItalic-webfont.ttf b/docs/fonts/OpenSans-SemiboldItalic-webfont.ttf new file mode 100755 index 000000000..d2d6318f6 Binary files /dev/null and b/docs/fonts/OpenSans-SemiboldItalic-webfont.ttf differ diff --git a/docs/fonts/OpenSans-SemiboldItalic-webfont.woff b/docs/fonts/OpenSans-SemiboldItalic-webfont.woff new file mode 100755 index 000000000..d4dfca402 Binary files /dev/null and b/docs/fonts/OpenSans-SemiboldItalic-webfont.woff differ diff --git a/docs/global.html b/docs/global.html new file mode 100644 index 000000000..cb9ad0459 --- /dev/null +++ b/docs/global.html @@ -0,0 +1,1346 @@ + + + + + + + + + Global - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Global +

+ + + + +
+
+ +

+ + + +

+ + + +
+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + +

Members

+ + + + +

+ (constant) FULL_QUALIFIED_NAME :String +

+ + + + +
+

This is an identifier with a namespace separator that begins with +a namespace separator, such as \Foo\Bar. The namespace \Foo is also +a fully qualified name.

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) ignoreStack +

+ + + + +
+

outputs some debug information on current token

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) MODE_BLOCK :String +

+ + + + +
+

The node is declared bracket enclosed code :

+
<?php
+declare(ticks=1) {
+// some statements
+}
+
+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) MODE_NONE :String +

+ + + + +
+

The node is declared as a simple statement. In order to make things simpler +children of the node are automatically collected until the next +declare statement.

+
<?php
+declare(ticks=1);
+// some statements
+declare(ticks=2);
+// some statements
+
+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) MODE_SHORT :String +

+ + + + +
+

The node is declared as a short tag syntax :

+
<?php
+declare(ticks=1):
+// some statements
+enddeclare;
+
+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) QUALIFIED_NAME :String +

+ + + + +
+

This is an identifier with a namespace separator, such as Foo\Bar

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) RELATIVE_NAME :String +

+ + + + +
+

This is an identifier starting with namespace, such as namespace\Foo\Bar.

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) TYPE_CONST :String +

+ + + + +
+

Importing a constant

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) TYPE_FUNC :String +

+ + + + +
+

Importing a function

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) TYPE_HEREDOC :String +

+ + + + +
+

The node is a shell execute string :

+
<?php
+echo <<<STR
+ Hello $world
+STR
+;
+
+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) TYPE_OFFSET :String +

+ + + + +
+

The node contains a list of constref / variables / expr :

+
<?php
+echo $foo->bar_$baz;
+
+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) TYPE_SHELL :String +

+ + + + +
+

The node is a shell execute string :

+
<?php
+echo `ls -larth $path`;
+
+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) TYPE_STRING :String +

+ + + + +
+

The node is a double quote string :

+
<?php
+echo "hello $world";
+
+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + +

+ (constant) UNQUALIFIED_NAME :String +

+ + + + +
+

This is an identifier without a namespace separator, such as Foo

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ getStringBuffer(buffer) → {String} +

+
+ + + + + +
+

Check if the inpyt is a buffer or a string

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
buffer + + + + Buffer + + + | + + + String + + + + + + + +

Input value that can be either a buffer or a string

+ +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/icons/home.svg b/docs/icons/home.svg new file mode 100644 index 000000000..676d2d385 --- /dev/null +++ b/docs/icons/home.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/docs/icons/search.svg b/docs/icons/search.svg new file mode 100644 index 000000000..ccc84b62c --- /dev/null +++ b/docs/icons/search.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 000000000..03dbbfec1 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,244 @@ + + + + + + + + + Home - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ + + + + + + + + + + + +
+
+

php-parser

+

+ +Coverage Status + + + + +

+

This javascript library parses PHP code and convert it to AST.

+

Installation

+

This library is distributed with npm :

+
npm install php-parser --save
+
+

Usage

+
// initialize the php parser factory class
+var fs = require('fs');
+var path = require('path');
+var engine = require('php-parser');
+
+// initialize a new parser instance
+var parser = new engine({
+  // some options :
+  parser: {
+    extractDoc: true,
+    php7: true
+  },
+  ast: {
+    withPositions: true
+  }
+});
+
+// Retrieve the AST from the specified source
+var eval = parser.parseEval('echo "Hello World";');
+
+// Retrieve an array of tokens (same as php function token_get_all)
+var tokens = parser.tokenGetAll('<?php echo "Hello World";');
+
+// Load a static file (Note: this file should exist on your computer)
+var phpFile = fs.readFileSync( './example.php' );
+
+// Log out results
+console.log( 'Eval parse:', eval );
+console.log( 'Tokens parse:', tokens );
+console.log( 'File parse:', parser.parseCode(phpFile) );
+
+
+

Sample AST output

+
{
+  'kind': 'program',
+  'children': [
+    {
+      'kind': 'echo',
+      'arguments': [
+        {
+          'kind': 'string',
+          'isDoubleQuote': true,
+          'value': 'Hello World'
+        }
+      ]
+    }
+  ]
+}
+
+
    +
  • Try it online (demo) : http://glayzzle.com/php-parser/
  • +
  • Or from AST Explorer : https://astexplorer.net/
  • +
+

API Overview

+

The main API exposes a class with the following methods :

+
    +
  • parseEval(String|Buffer) : parse a PHP code in eval style mode (without php open tags)
  • +
  • parseCode(String|Buffer, String filename) : parse a PHP code by using php open tags.
  • +
  • tokenGetAll(String|Buffer) : retrieves a list of all tokens from the specified input.
  • +
+

You can also pass options that change the behavior of the parser/lexer.

+

Documentation

+ + +
    +
  • prettier/plugin-php : Prettier PHP Plugin
  • +
  • babel-preset-php : Babel preset for converting PHP syntax to JavaScript. It can run subset of PHP in the browser or in Node.js
  • +
  • wp-pot : Generate pot file for WordPress plugins and themes
  • +
  • crane : PHP Intellisense/code-completion for VS Code
  • +
  • php-unparser : Produce code that uses the style format recommended by PSR-1 and PSR-2.
  • +
  • php-writer : Update PHP scripts from their AST
  • +
  • ts-php-inspections : Provide PHP code inspections written in typescript
  • +
  • php-reflection : Reflection API for PHP files
  • +
  • vscode-phpunit : vscode phpunit extension
  • +
  • lua2php : a Lua to PHP transpiler
  • +
+
+

You can add here your own project by opening an issue request.

+
+

License

+

This library is released under BSD-3 license clause.

+

FOSSA Status

+
+
+ + + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/index.js.html b/docs/index.js.html new file mode 100644 index 000000000..0d6439c04 --- /dev/null +++ b/docs/index.js.html @@ -0,0 +1,358 @@ + + + + + + + + + + + index.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ index.js +

+ + + + + +
+
+
/*!
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const lexer = require("./lexer");
+const parser = require("./parser");
+const tokens = require("./tokens");
+const AST = require("./ast");
+
+/**
+ * @private
+ */
+function combine(src, to) {
+  const keys = Object.keys(src);
+  let i = keys.length;
+  while (i--) {
+    const k = keys[i];
+    const val = src[k];
+    if (val === null) {
+      delete to[k];
+    } else if (typeof val === "function") {
+      to[k] = val.bind(to);
+    } else if (Array.isArray(val)) {
+      to[k] = Array.isArray(to[k]) ? to[k].concat(val) : val;
+    } else if (typeof val === "object") {
+      to[k] = typeof to[k] === "object" ? combine(val, to[k]) : val;
+    } else {
+      to[k] = val;
+    }
+  }
+  return to;
+}
+
+/**
+ * Initialise a new parser instance with the specified options
+ *
+ * @class
+ * @tutorial Engine
+ * @example
+ * var parser = require('php-parser');
+ * var instance = new parser({
+ *   parser: {
+ *     extractDoc: true,
+ *     suppressErrors: true,
+ *     php7: true
+ *   },
+ *   ast: {
+ *     withPositions: true
+ *   },
+ *   lexer: {
+ *     short_tags: true,
+ *     asp_tags: true
+ *   }
+ * });
+ *
+ * var evalAST = instance.parseEval('some php code');
+ * var codeAST = instance.parseCode('<?php some php code', 'foo.php');
+ * var tokens = instance.tokenGetAll('<?php some php code');
+ *
+ * @param {Object} options - List of options
+ * @property {Lexer} lexer
+ * @property {Parser} parser
+ * @property {AST} ast
+ * @property {Object} tokens
+ */
+const engine = function(options) {
+  if (typeof this === "function") {
+    return new this(options);
+  }
+  this.tokens = tokens;
+  this.lexer = new lexer(this);
+  this.ast = new AST();
+  this.parser = new parser(this.lexer, this.ast);
+  if (options && typeof options === "object") {
+    // disable php7 from lexer if already disabled from parser
+    if (options.parser && options.parser.php7 === false) {
+      if (!options.lexer) {
+        options.lexer = {};
+      }
+      options.lexer.php7 = false;
+    }
+    combine(options, this);
+  }
+};
+
+/**
+ * Check if the inpyt is a buffer or a string
+ * @param  {Buffer|String} buffer Input value that can be either a buffer or a string
+ * @return {String}   Returns the string from input
+ */
+const getStringBuffer = function(buffer) {
+  return Buffer.isBuffer(buffer) ? buffer.toString() : buffer;
+};
+
+/**
+ * Creates a new instance (Helper)
+ * @param {Object} options
+ * @return {Engine}
+ * @private
+ */
+engine.create = function(options) {
+  return new engine(options);
+};
+
+/**
+ * Evaluate the buffer
+ * @private
+ */
+engine.parseEval = function(buffer, options) {
+  const self = new engine(options);
+  return self.parseEval(buffer);
+};
+
+/**
+ * Parse an evaluating mode string (no need to open php tags)
+ * @param {String} buffer
+ * @return {Program}
+ */
+engine.prototype.parseEval = function(buffer) {
+  this.lexer.mode_eval = true;
+  this.lexer.all_tokens = false;
+  buffer = getStringBuffer(buffer);
+  return this.parser.parse(buffer, "eval");
+};
+
+/**
+ * Static function that parse a php code with open/close tags
+ * @private
+ */
+engine.parseCode = function(buffer, filename, options) {
+  if (typeof filename === "object" && !options) {
+    // retro-compatibility
+    options = filename;
+    filename = "unknown";
+  }
+  const self = new engine(options);
+  return self.parseCode(buffer, filename);
+};
+
+/**
+ * Function that parse a php code with open/close tags
+ *
+ * Sample code :
+ * ```php
+ * <?php $x = 1;
+ * ```
+ *
+ * Usage :
+ * ```js
+ * var parser = require('php-parser');
+ * var phpParser = new parser({
+ *   // some options
+ * });
+ * var ast = phpParser.parseCode('...php code...', 'foo.php');
+ * ```
+ * @param {String} buffer - The code to be parsed
+ * @param {String} filename - Filename
+ * @return {Program}
+ */
+engine.prototype.parseCode = function(buffer, filename) {
+  this.lexer.mode_eval = false;
+  this.lexer.all_tokens = false;
+  buffer = getStringBuffer(buffer);
+  return this.parser.parse(buffer, filename);
+};
+
+/**
+ * Split the buffer into tokens
+ * @private
+ */
+engine.tokenGetAll = function(buffer, options) {
+  const self = new engine(options);
+  return self.tokenGetAll(buffer);
+};
+
+/**
+ * Extract tokens from the specified buffer.
+ * > Note that the output tokens are *STRICLY* similar to PHP function `token_get_all`
+ * @param {String} buffer
+ * @return {String[]} - Each item can be a string or an array with following informations [token_name, text, line_number]
+ */
+engine.prototype.tokenGetAll = function(buffer) {
+  this.lexer.mode_eval = false;
+  this.lexer.all_tokens = true;
+  buffer = getStringBuffer(buffer);
+  const EOF = this.lexer.EOF;
+  const names = this.tokens.values;
+  this.lexer.setInput(buffer);
+  let token = this.lexer.lex() || EOF;
+  const result = [];
+  while (token != EOF) {
+    let entry = this.lexer.yytext;
+    if (names.hasOwnProperty(token)) {
+      entry = [names[token], entry, this.lexer.yylloc.first_line];
+    }
+    result.push(entry);
+    token = this.lexer.lex() || EOF;
+  }
+  return result;
+};
+
+// exports the function
+module.exports = engine;
+
+// makes libraries public
+module.exports.tokens = tokens;
+module.exports.lexer = lexer;
+module.exports.AST = AST;
+module.exports.parser = parser;
+module.exports.combine = combine;
+
+// allow the default export in index.d.ts
+module.exports.default = engine;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/lexer.html b/docs/lexer.html new file mode 100644 index 000000000..1c522738e --- /dev/null +++ b/docs/lexer.html @@ -0,0 +1,983 @@ + + + + + + + + + lexer - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ lexer +

+ + + + +
+
+ +

+ + lexer + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new lexer() +

+
+ + + + + +
+

This is the php lexer. It will tokenize the string for helping the +parser to build the AST from its grammar.

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
EOF + + + + Integer + + + + + + + + +
all_tokens + + + + Boolean + + + + + + + +

defines if all tokens must be retrieved (used by token_get_all only)

+
comment_tokens + + + + Boolean + + + + + + + +

extracts comments tokens

+
mode_eval + + + + Boolean + + + + + + + +

enables the evald mode (ignore opening tags)

+
asp_tags + + + + Boolean + + + + + + + +

disables by default asp tags mode

+
short_tags + + + + Boolean + + + + + + + +

enables by default short tags mode

+
keywords + + + + Object + + + + + + + +

List of php keyword

+
castKeywords + + + + Object + + + + + + + +

List of php keywords for type casting

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ getState() +

+
+ + + + + +
+

Gets the current state

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ input() +

+
+ + + + + +
+

consumes and returns one char from the input

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setInput() +

+
+ + + + + +
+

Initialize the lexer with the specified input

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setState() +

+
+ + + + + +
+

Sets the current lexer state

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ unput() +

+
+ + + + + +
+

revert eating specified size

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/lexer.js.html b/docs/lexer.js.html new file mode 100644 index 000000000..7326cddd2 --- /dev/null +++ b/docs/lexer.js.html @@ -0,0 +1,603 @@ + + + + + + + + + + + lexer.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ lexer.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+/**
+ * This is the php lexer. It will tokenize the string for helping the
+ * parser to build the AST from its grammar.
+ *
+ * @class
+ * @property {Integer} EOF
+ * @property {Boolean} all_tokens defines if all tokens must be retrieved (used by token_get_all only)
+ * @property {Boolean} comment_tokens extracts comments tokens
+ * @property {Boolean} mode_eval enables the evald mode (ignore opening tags)
+ * @property {Boolean} asp_tags disables by default asp tags mode
+ * @property {Boolean} short_tags enables by default short tags mode
+ * @property {Object} keywords List of php keyword
+ * @property {Object} castKeywords List of php keywords for type casting
+ */
+const lexer = function(engine) {
+  this.engine = engine;
+  this.tok = this.engine.tokens.names;
+  this.EOF = 1;
+  this.debug = false;
+  this.all_tokens = true;
+  this.comment_tokens = false;
+  this.mode_eval = false;
+  this.asp_tags = false;
+  this.short_tags = true;
+  this.php7 = true;
+  this.yyprevcol = 0;
+  this.keywords = {
+    __class__: this.tok.T_CLASS_C,
+    __trait__: this.tok.T_TRAIT_C,
+    __function__: this.tok.T_FUNC_C,
+    __method__: this.tok.T_METHOD_C,
+    __line__: this.tok.T_LINE,
+    __file__: this.tok.T_FILE,
+    __dir__: this.tok.T_DIR,
+    __namespace__: this.tok.T_NS_C,
+    exit: this.tok.T_EXIT,
+    die: this.tok.T_EXIT,
+    function: this.tok.T_FUNCTION,
+    const: this.tok.T_CONST,
+    return: this.tok.T_RETURN,
+    try: this.tok.T_TRY,
+    catch: this.tok.T_CATCH,
+    finally: this.tok.T_FINALLY,
+    throw: this.tok.T_THROW,
+    if: this.tok.T_IF,
+    elseif: this.tok.T_ELSEIF,
+    endif: this.tok.T_ENDIF,
+    else: this.tok.T_ELSE,
+    while: this.tok.T_WHILE,
+    endwhile: this.tok.T_ENDWHILE,
+    do: this.tok.T_DO,
+    for: this.tok.T_FOR,
+    endfor: this.tok.T_ENDFOR,
+    foreach: this.tok.T_FOREACH,
+    endforeach: this.tok.T_ENDFOREACH,
+    declare: this.tok.T_DECLARE,
+    enddeclare: this.tok.T_ENDDECLARE,
+    instanceof: this.tok.T_INSTANCEOF,
+    as: this.tok.T_AS,
+    switch: this.tok.T_SWITCH,
+    endswitch: this.tok.T_ENDSWITCH,
+    case: this.tok.T_CASE,
+    default: this.tok.T_DEFAULT,
+    break: this.tok.T_BREAK,
+    continue: this.tok.T_CONTINUE,
+    goto: this.tok.T_GOTO,
+    echo: this.tok.T_ECHO,
+    print: this.tok.T_PRINT,
+    class: this.tok.T_CLASS,
+    interface: this.tok.T_INTERFACE,
+    trait: this.tok.T_TRAIT,
+    extends: this.tok.T_EXTENDS,
+    implements: this.tok.T_IMPLEMENTS,
+    new: this.tok.T_NEW,
+    clone: this.tok.T_CLONE,
+    var: this.tok.T_VAR,
+    eval: this.tok.T_EVAL,
+    include: this.tok.T_INCLUDE,
+    include_once: this.tok.T_INCLUDE_ONCE,
+    require: this.tok.T_REQUIRE,
+    require_once: this.tok.T_REQUIRE_ONCE,
+    namespace: this.tok.T_NAMESPACE,
+    use: this.tok.T_USE,
+    insteadof: this.tok.T_INSTEADOF,
+    global: this.tok.T_GLOBAL,
+    isset: this.tok.T_ISSET,
+    empty: this.tok.T_EMPTY,
+    __halt_compiler: this.tok.T_HALT_COMPILER,
+    static: this.tok.T_STATIC,
+    abstract: this.tok.T_ABSTRACT,
+    final: this.tok.T_FINAL,
+    private: this.tok.T_PRIVATE,
+    protected: this.tok.T_PROTECTED,
+    public: this.tok.T_PUBLIC,
+    unset: this.tok.T_UNSET,
+    list: this.tok.T_LIST,
+    array: this.tok.T_ARRAY,
+    callable: this.tok.T_CALLABLE,
+    or: this.tok.T_LOGICAL_OR,
+    and: this.tok.T_LOGICAL_AND,
+    xor: this.tok.T_LOGICAL_XOR
+  };
+  this.castKeywords = {
+    int: this.tok.T_INT_CAST,
+    integer: this.tok.T_INT_CAST,
+    real: this.tok.T_DOUBLE_CAST,
+    double: this.tok.T_DOUBLE_CAST,
+    float: this.tok.T_DOUBLE_CAST,
+    string: this.tok.T_STRING_CAST,
+    binary: this.tok.T_STRING_CAST,
+    array: this.tok.T_ARRAY_CAST,
+    object: this.tok.T_OBJECT_CAST,
+    bool: this.tok.T_BOOL_CAST,
+    boolean: this.tok.T_BOOL_CAST,
+    unset: this.tok.T_UNSET_CAST
+  };
+};
+
+/**
+ * Initialize the lexer with the specified input
+ */
+lexer.prototype.setInput = function(input) {
+  this._input = input;
+  this.size = input.length;
+  this.yylineno = 1;
+  this.offset = 0;
+  this.yyprevcol = 0;
+  this.yytext = "";
+  this.yylloc = {
+    first_offset: 0,
+    first_line: 1,
+    first_column: 0,
+    prev_offset: 0,
+    prev_line: 1,
+    prev_column: 0,
+    last_line: 1,
+    last_column: 0
+  };
+  this.tokens = [];
+  this.done = this.offset >= this.size;
+  if (!this.all_tokens && this.mode_eval) {
+    this.conditionStack = ["INITIAL"];
+    this.begin("ST_IN_SCRIPTING");
+  } else {
+    this.conditionStack = [];
+    this.begin("INITIAL");
+  }
+  return this;
+};
+
+/**
+ * consumes and returns one char from the input
+ */
+lexer.prototype.input = function() {
+  const ch = this._input[this.offset];
+  if (!ch) return "";
+  this.yytext += ch;
+  this.offset++;
+  if (ch === "\r" && this._input[this.offset] === "\n") {
+    this.yytext += "\n";
+    this.offset++;
+  }
+  if (ch === "\n" || ch === "\r") {
+    this.yylloc.last_line = ++this.yylineno;
+    this.yyprevcol = this.yylloc.last_column;
+    this.yylloc.last_column = 0;
+  } else {
+    this.yylloc.last_column++;
+  }
+  return ch;
+};
+
+/**
+ * revert eating specified size
+ */
+lexer.prototype.unput = function(size) {
+  if (size === 1) {
+    // 1 char unput (most cases)
+    this.offset--;
+    if (
+      this._input[this.offset] === "\n" &&
+      this._input[this.offset - 1] === "\r"
+    ) {
+      this.offset--;
+      size++;
+    }
+    if (
+      this._input[this.offset] === "\r" ||
+      this._input[this.offset] === "\n"
+    ) {
+      this.yylloc.last_line--;
+      this.yylineno--;
+      this.yylloc.last_column = this.yyprevcol;
+    } else {
+      this.yylloc.last_column--;
+    }
+    this.yytext = this.yytext.substring(0, this.yytext.length - size);
+  } else if (size > 0) {
+    this.offset -= size;
+    if (size < this.yytext.length) {
+      this.yytext = this.yytext.substring(0, this.yytext.length - size);
+      // re-calculate position
+      this.yylloc.last_line = this.yylloc.first_line;
+      this.yylloc.last_column = this.yyprevcol = this.yylloc.first_column;
+      for (let i = 0; i < this.yytext.length; i++) {
+        let c = this.yytext[i];
+        if (c === "\r") {
+          c = this.yytext[++i];
+          this.yyprevcol = this.yylloc.last_column;
+          this.yylloc.last_line++;
+          this.yylloc.last_column = 0;
+          if (c !== "\n") {
+            if (c === "\r") {
+              this.yylloc.last_line++;
+            } else {
+              this.yylloc.last_column++;
+            }
+          }
+        } else if (c === "\n") {
+          this.yyprevcol = this.yylloc.last_column;
+          this.yylloc.last_line++;
+          this.yylloc.last_column = 0;
+        } else {
+          this.yylloc.last_column++;
+        }
+      }
+      this.yylineno = this.yylloc.last_line;
+    } else {
+      // reset full text
+      this.yytext = "";
+      this.yylloc.last_line = this.yylineno = this.yylloc.first_line;
+      this.yylloc.last_column = this.yylloc.first_column;
+    }
+  }
+
+  return this;
+};
+
+// check if the text matches
+lexer.prototype.tryMatch = function(text) {
+  return text === this.ahead(text.length);
+};
+
+// check if the text matches
+lexer.prototype.tryMatchCaseless = function(text) {
+  return text === this.ahead(text.length).toLowerCase();
+};
+
+// look ahead
+lexer.prototype.ahead = function(size) {
+  let text = this._input.substring(this.offset, this.offset + size);
+  if (
+    text[text.length - 1] === "\r" &&
+    this._input[this.offset + size + 1] === "\n"
+  ) {
+    text += "\n";
+  }
+  return text;
+};
+
+// consume the specified size
+lexer.prototype.consume = function(size) {
+  for (let i = 0; i < size; i++) {
+    const ch = this._input[this.offset];
+    if (!ch) break;
+    this.yytext += ch;
+    this.offset++;
+    if (ch === "\r" && this._input[this.offset] === "\n") {
+      this.yytext += "\n";
+      this.offset++;
+      i++;
+    }
+    if (ch === "\n" || ch === "\r") {
+      this.yylloc.last_line = ++this.yylineno;
+      this.yyprevcol = this.yylloc.last_column;
+      this.yylloc.last_column = 0;
+    } else {
+      this.yylloc.last_column++;
+    }
+  }
+  return this;
+};
+
+/**
+ * Gets the current state
+ */
+lexer.prototype.getState = function() {
+  return {
+    yytext: this.yytext,
+    offset: this.offset,
+    yylineno: this.yylineno,
+    yyprevcol: this.yyprevcol,
+    yylloc: {
+      first_offset: this.yylloc.first_offset,
+      first_line: this.yylloc.first_line,
+      first_column: this.yylloc.first_column,
+      last_line: this.yylloc.last_line,
+      last_column: this.yylloc.last_column
+    }
+  };
+};
+
+/**
+ * Sets the current lexer state
+ */
+lexer.prototype.setState = function(state) {
+  this.yytext = state.yytext;
+  this.offset = state.offset;
+  this.yylineno = state.yylineno;
+  this.yyprevcol = state.yyprevcol;
+  this.yylloc = state.yylloc;
+  return this;
+};
+
+// prepend next token
+lexer.prototype.appendToken = function(value, ahead) {
+  this.tokens.push([value, ahead]);
+  return this;
+};
+
+// return next match that has a token
+lexer.prototype.lex = function() {
+  this.yylloc.prev_offset = this.offset;
+  this.yylloc.prev_line = this.yylloc.last_line;
+  this.yylloc.prev_column = this.yylloc.last_column;
+  let token = this.next() || this.lex();
+  if (!this.all_tokens) {
+    while (
+      token === this.tok.T_WHITESPACE || // ignore white space
+      (!this.comment_tokens &&
+        (token === this.tok.T_COMMENT || // ignore single lines comments
+          token === this.tok.T_DOC_COMMENT)) || // ignore doc comments
+      // ignore open tags
+      token === this.tok.T_OPEN_TAG
+    ) {
+      token = this.next() || this.lex();
+    }
+    if (token == this.tok.T_OPEN_TAG_WITH_ECHO) {
+      // https://github.com/php/php-src/blob/7ff186434e82ee7be7c59d0db9a976641cf7b09c/Zend/zend_compile.c#L1683
+      // open tag with echo statement
+      return this.tok.T_ECHO;
+    } else if (token === this.tok.T_CLOSE_TAG) {
+      // https://github.com/php/php-src/blob/7ff186434e82ee7be7c59d0db9a976641cf7b09c/Zend/zend_compile.c#L1680
+      return ";"; /* implicit ; */
+    }
+  }
+  if (!this.yylloc.prev_offset) {
+    this.yylloc.prev_offset = this.yylloc.first_offset;
+    this.yylloc.prev_line = this.yylloc.first_line;
+    this.yylloc.prev_column = this.yylloc.first_column;
+  }
+  /*else if (this.yylloc.prev_offset === this.offset && this.offset !== this.size) {
+    throw new Error('Infinite loop @ ' + this.offset + ' / ' + this.size);
+  }*/
+  return token;
+};
+
+// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack)
+lexer.prototype.begin = function(condition) {
+  this.conditionStack.push(condition);
+  this.curCondition = condition;
+  this.stateCb = this["match" + condition];
+  if (typeof this.stateCb !== "function") {
+    throw new Error('Undefined condition state "' + condition + '"');
+  }
+  return this;
+};
+
+// pop the previously active lexer condition state off the condition stack
+lexer.prototype.popState = function() {
+  const n = this.conditionStack.length - 1;
+  const condition = n > 0 ? this.conditionStack.pop() : this.conditionStack[0];
+  this.curCondition = this.conditionStack[this.conditionStack.length - 1];
+  this.stateCb = this["match" + this.curCondition];
+  if (typeof this.stateCb !== "function") {
+    throw new Error('Undefined condition state "' + this.curCondition + '"');
+  }
+  return condition;
+};
+
+// return next match in input
+lexer.prototype.next = function() {
+  let token;
+  if (!this._input) {
+    this.done = true;
+  }
+  this.yylloc.first_offset = this.offset;
+  this.yylloc.first_line = this.yylloc.last_line;
+  this.yylloc.first_column = this.yylloc.last_column;
+  this.yytext = "";
+  if (this.done) {
+    this.yylloc.prev_offset = this.yylloc.first_offset;
+    this.yylloc.prev_line = this.yylloc.first_line;
+    this.yylloc.prev_column = this.yylloc.first_column;
+    return this.EOF;
+  }
+  if (this.tokens.length > 0) {
+    token = this.tokens.shift();
+    if (typeof token[1] === "object") {
+      this.setState(token[1]);
+    } else {
+      this.consume(token[1]);
+    }
+    token = token[0];
+  } else {
+    token = this.stateCb.apply(this, []);
+  }
+  if (this.offset >= this.size && this.tokens.length === 0) {
+    this.done = true;
+  }
+  if (this.debug) {
+    let tName = token;
+    if (typeof tName === "number") {
+      tName = this.engine.tokens.values[tName];
+    } else {
+      tName = '"' + tName + '"';
+    }
+    const e = new Error(
+      tName +
+        "\tfrom " +
+        this.yylloc.first_line +
+        "," +
+        this.yylloc.first_column +
+        "\t - to " +
+        this.yylloc.last_line +
+        "," +
+        this.yylloc.last_column +
+        '\t"' +
+        this.yytext +
+        '"'
+    );
+    // eslint-disable-next-line no-console
+    console.error(e.stack);
+  }
+  return token;
+};
+
+// extends the lexer with states
+[
+  require("./lexer/comments.js"),
+  require("./lexer/initial.js"),
+  require("./lexer/numbers.js"),
+  require("./lexer/property.js"),
+  require("./lexer/scripting.js"),
+  require("./lexer/strings.js"),
+  require("./lexer/tokens.js"),
+  require("./lexer/utils.js")
+].forEach(function(ext) {
+  for (const k in ext) {
+    lexer.prototype[k] = ext[k];
+  }
+});
+
+module.exports = lexer;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/lexer.md b/docs/lexer.md deleted file mode 100644 index 8f3cbc4bb..000000000 --- a/docs/lexer.md +++ /dev/null @@ -1,81 +0,0 @@ - - -## lexer - -This is the php lexer. It will tokenize the string for helping the -parser to build the AST from its grammar. - -**Parameters** - -- `engine` - -**Properties** - -- `EOF` **Integer** -- `all_tokens` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** defines if all tokens must be retrieved (used by token_get_all only) -- `comment_tokens` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** extracts comments tokens -- `mode_eval` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** enables the evald mode (ignore opening tags) -- `asp_tags` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** disables by default asp tags mode -- `short_tags` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** enables by default short tags mode -- `keywords` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** List of php keyword -- `castKeywords` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** List of php keywords for type casting - -### setInput - -Initialize the lexer with the specified input - -**Parameters** - -- `input` - -### input - -consumes and returns one char from the input - -**Parameters** - -- `size` - -### unput - -revert eating specified size - -**Parameters** - -- `size` - -### getState - -Gets the current state - -### setState - -Sets the current lexer state - -**Parameters** - -- `state` - -## T_COMMENT - -Reads a single line comment - -## T_DOC_COMMENT - -Behaviour : - -## T_END_HEREDOC - -edge case : empty now doc \* - -## ch - -SCANNING CONTENTS \* - -## ch - -edge case : empty here doc \* - -## ch - -SCANNING CONTENTS \* diff --git a/docs/lexer_comments.js.html b/docs/lexer_comments.js.html new file mode 100644 index 000000000..8981c42c5 --- /dev/null +++ b/docs/lexer_comments.js.html @@ -0,0 +1,205 @@ + + + + + + + + + + + lexer/comments.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ lexer/comments.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * Reads a single line comment
+   */
+  T_COMMENT: function() {
+    while (this.offset < this.size) {
+      const ch = this.input();
+      if (ch === "\n" || ch === "\r") {
+        return this.tok.T_COMMENT;
+      } else if (
+        ch === "?" &&
+        !this.aspTagMode &&
+        this._input[this.offset] === ">"
+      ) {
+        this.unput(1);
+        return this.tok.T_COMMENT;
+      } else if (
+        ch === "%" &&
+        this.aspTagMode &&
+        this._input[this.offset] === ">"
+      ) {
+        this.unput(1);
+        return this.tok.T_COMMENT;
+      }
+    }
+    return this.tok.T_COMMENT;
+  },
+  /**
+   * Behaviour : https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1927
+   */
+  T_DOC_COMMENT: function() {
+    let ch = this.input();
+    let token = this.tok.T_COMMENT;
+    if (ch === "*") {
+      // started with '/*' , check is next is '*'
+      ch = this.input();
+      if (this.is_WHITESPACE()) {
+        // check if next is WHITESPACE
+        token = this.tok.T_DOC_COMMENT;
+      }
+      if (ch === "/") {
+        return token;
+      } else {
+        this.unput(1); // reset
+      }
+    }
+    while (this.offset < this.size) {
+      ch = this.input();
+      if (ch === "*" && this._input[this.offset] === "/") {
+        this.input();
+        break;
+      }
+    }
+    return token;
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/lexer_strings.js.html b/docs/lexer_strings.js.html new file mode 100644 index 000000000..1460d90ae --- /dev/null +++ b/docs/lexer_strings.js.html @@ -0,0 +1,559 @@ + + + + + + + + + + + lexer/strings.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ lexer/strings.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  T_CONSTANT_ENCAPSED_STRING: function() {
+    let ch;
+    while (this.offset < this.size) {
+      ch = this.input();
+      if (ch == "\\") {
+        this.input();
+      } else if (ch == "'") {
+        break;
+      }
+    }
+    return this.tok.T_CONSTANT_ENCAPSED_STRING;
+  },
+  // check if matching a HEREDOC state
+  is_HEREDOC: function() {
+    const revert = this.offset;
+    if (
+      this._input[this.offset - 1] === "<" &&
+      this._input[this.offset] === "<" &&
+      this._input[this.offset + 1] === "<"
+    ) {
+      this.offset += 3;
+
+      // optional tabs / spaces
+      if (this.is_TABSPACE()) {
+        while (this.offset < this.size) {
+          this.offset++;
+          if (!this.is_TABSPACE()) {
+            break;
+          }
+        }
+      }
+
+      // optional quotes
+      let tChar = this._input[this.offset - 1];
+      if (tChar === "'" || tChar === '"') {
+        this.offset++;
+      } else {
+        tChar = null;
+      }
+
+      // required label
+      if (this.is_LABEL_START()) {
+        let yyoffset = this.offset - 1;
+        while (this.offset < this.size) {
+          this.offset++;
+          if (!this.is_LABEL()) {
+            break;
+          }
+        }
+        const yylabel = this._input.substring(yyoffset, this.offset - 1);
+        if (!tChar || tChar === this._input[this.offset - 1]) {
+          // required ending quote
+          if (tChar) this.offset++;
+          // require newline
+          if (
+            this._input[this.offset - 1] === "\r" ||
+            this._input[this.offset - 1] === "\n"
+          ) {
+            // go go go
+            this.heredoc_label = yylabel;
+            yyoffset = this.offset - revert;
+            this.offset = revert;
+            this.consume(yyoffset);
+            if (tChar === "'") {
+              this.begin("ST_NOWDOC");
+            } else {
+              this.begin("ST_HEREDOC");
+            }
+            return this.tok.T_START_HEREDOC;
+          }
+        }
+      }
+    }
+    this.offset = revert;
+    return false;
+  },
+  ST_DOUBLE_QUOTES: function() {
+    let ch;
+    while (this.offset < this.size) {
+      ch = this.input();
+      if (ch == "\\") {
+        this.input();
+      } else if (ch == '"') {
+        break;
+      } else if (ch == "$") {
+        ch = this.input();
+        if (ch == "{" || this.is_LABEL_START()) {
+          this.unput(2);
+          break;
+        }
+        if (ch) this.unput(1);
+      } else if (ch == "{") {
+        ch = this.input();
+        if (ch == "$") {
+          this.unput(2);
+          break;
+        }
+        if (ch) this.unput(1);
+      }
+    }
+    if (ch == '"') {
+      return this.tok.T_CONSTANT_ENCAPSED_STRING;
+    } else {
+      let prefix = 1;
+      if (this.yytext[0] === "b" || this.yytext[0] === "B") {
+        prefix = 2;
+      }
+      if (this.yytext.length > 2) {
+        this.appendToken(
+          this.tok.T_ENCAPSED_AND_WHITESPACE,
+          this.yytext.length - prefix
+        );
+      }
+      this.unput(this.yytext.length - prefix);
+      this.begin("ST_DOUBLE_QUOTES");
+      return this.yytext;
+    }
+  },
+
+  // check if its a DOC end sequence
+  isDOC_MATCH: function() {
+    // @fixme : check if out of text limits
+    if (
+      this._input.substring(
+        this.offset - 1,
+        this.offset - 1 + this.heredoc_label.length
+      ) === this.heredoc_label
+    ) {
+      const ch = this._input[this.offset - 1 + this.heredoc_label.length];
+      if (ch === "\n" || ch === "\r" || ch === ";") {
+        return true;
+      }
+    }
+    return false;
+  },
+
+  matchST_NOWDOC: function() {
+    /** edge case : empty now doc **/
+    if (this.isDOC_MATCH()) {
+      // @fixme : never reached (may be caused by quotes)
+      this.consume(this.heredoc_label.length);
+      this.popState();
+      return this.tok.T_END_HEREDOC;
+    }
+    /** SCANNING CONTENTS **/
+    let ch = this._input[this.offset - 1];
+    while (this.offset < this.size) {
+      if (ch === "\n" || ch === "\r") {
+        ch = this.input();
+        if (this.isDOC_MATCH()) {
+          this.unput(1).popState();
+          this.appendToken(this.tok.T_END_HEREDOC, this.heredoc_label.length);
+          return this.tok.T_ENCAPSED_AND_WHITESPACE;
+        }
+      } else {
+        ch = this.input();
+      }
+    }
+    // too bad ! reached end of document (will get a parse error)
+    return this.tok.T_ENCAPSED_AND_WHITESPACE;
+  },
+
+  matchST_HEREDOC: function() {
+    /** edge case : empty here doc **/
+    let ch = this.input();
+    if (this.isDOC_MATCH()) {
+      this.consume(this.heredoc_label.length - 1);
+      this.popState();
+      return this.tok.T_END_HEREDOC;
+    }
+    /** SCANNING CONTENTS **/
+    while (this.offset < this.size) {
+      if (ch === "\\") {
+        ch = this.input(); // ignore next
+        if (ch !== "\n" && ch !== "\r") {
+          ch = this.input();
+        }
+      }
+
+      if (ch === "\n" || ch === "\r") {
+        ch = this.input();
+        if (this.isDOC_MATCH()) {
+          this.unput(1).popState();
+          this.appendToken(this.tok.T_END_HEREDOC, this.heredoc_label.length);
+          return this.tok.T_ENCAPSED_AND_WHITESPACE;
+        }
+      } else if (ch === "$") {
+        ch = this.input();
+        if (ch === "{") {
+          // start of ${
+          this.begin("ST_LOOKING_FOR_VARNAME");
+          if (this.yytext.length > 2) {
+            this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2);
+            this.unput(2);
+            return this.tok.T_ENCAPSED_AND_WHITESPACE;
+          } else {
+            return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
+          }
+        } else if (this.is_LABEL_START()) {
+          // start of $var...
+          const yyoffset = this.offset;
+          const next = this.consume_VARIABLE();
+          if (this.yytext.length > this.offset - yyoffset + 2) {
+            this.appendToken(next, this.offset - yyoffset + 2);
+            this.unput(this.offset - yyoffset + 2);
+            return this.tok.T_ENCAPSED_AND_WHITESPACE;
+          } else {
+            return next;
+          }
+          //console.log(this.yytext);
+        }
+      } else if (ch === "{") {
+        ch = this.input();
+        if (ch === "$") {
+          // start of {$...
+          this.begin("ST_IN_SCRIPTING");
+          if (this.yytext.length > 2) {
+            this.appendToken(this.tok.T_CURLY_OPEN, 1);
+            this.unput(2);
+            return this.tok.T_ENCAPSED_AND_WHITESPACE;
+          } else {
+            this.unput(1);
+            return this.tok.T_CURLY_OPEN;
+          }
+        }
+      } else {
+        ch = this.input();
+      }
+    }
+
+    // too bad ! reached end of document (will get a parse error)
+    return this.tok.T_ENCAPSED_AND_WHITESPACE;
+  },
+
+  consume_VARIABLE: function() {
+    this.consume_LABEL();
+    const ch = this.input();
+    if (ch == "[") {
+      this.unput(1);
+      this.begin("ST_VAR_OFFSET");
+      return this.tok.T_VARIABLE;
+    } else if (ch === "-") {
+      if (this.input() === ">") {
+        this.input();
+        if (this.is_LABEL_START()) {
+          this.begin("ST_LOOKING_FOR_PROPERTY");
+        }
+        this.unput(3);
+        return this.tok.T_VARIABLE;
+      } else {
+        this.unput(2);
+      }
+    } else {
+      if (ch) this.unput(1);
+    }
+    return this.tok.T_VARIABLE;
+  },
+  // HANDLES BACKQUOTES
+  matchST_BACKQUOTE: function() {
+    let ch = this.input();
+    if (ch === "$") {
+      ch = this.input();
+      if (ch === "{") {
+        this.begin("ST_LOOKING_FOR_VARNAME");
+        return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
+      } else if (this.is_LABEL_START()) {
+        const tok = this.consume_VARIABLE();
+        return tok;
+      }
+    } else if (ch === "{") {
+      if (this._input[this.offset] === "$") {
+        this.begin("ST_IN_SCRIPTING");
+        return this.tok.T_CURLY_OPEN;
+      }
+    } else if (ch === "`") {
+      this.popState();
+      return "`";
+    }
+
+    // any char
+    while (this.offset < this.size) {
+      if (ch === "\\") {
+        this.input();
+      } else if (ch === "`") {
+        this.unput(1);
+        this.popState();
+        this.appendToken("`", 1);
+        break;
+      } else if (ch === "$") {
+        ch = this.input();
+        if (ch === "{") {
+          this.begin("ST_LOOKING_FOR_VARNAME");
+          if (this.yytext.length > 2) {
+            this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2);
+            this.unput(2);
+            return this.tok.T_ENCAPSED_AND_WHITESPACE;
+          } else {
+            return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
+          }
+        } else if (this.is_LABEL_START()) {
+          // start of $var...
+          const yyoffset = this.offset;
+          const next = this.consume_VARIABLE();
+          if (this.yytext.length > this.offset - yyoffset + 2) {
+            this.appendToken(next, this.offset - yyoffset + 2);
+            this.unput(this.offset - yyoffset + 2);
+            return this.tok.T_ENCAPSED_AND_WHITESPACE;
+          } else {
+            return next;
+          }
+        }
+        continue;
+      } else if (ch === "{") {
+        ch = this.input();
+        if (ch === "$") {
+          // start of {$...
+          this.begin("ST_IN_SCRIPTING");
+          if (this.yytext.length > 2) {
+            this.appendToken(this.tok.T_CURLY_OPEN, 1);
+            this.unput(2);
+            return this.tok.T_ENCAPSED_AND_WHITESPACE;
+          } else {
+            this.unput(1);
+            return this.tok.T_CURLY_OPEN;
+          }
+        }
+        continue;
+      }
+      ch = this.input();
+    }
+    return this.tok.T_ENCAPSED_AND_WHITESPACE;
+  },
+
+  matchST_DOUBLE_QUOTES: function() {
+    let ch = this.input();
+    if (ch === "$") {
+      ch = this.input();
+      if (ch === "{") {
+        this.begin("ST_LOOKING_FOR_VARNAME");
+        return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
+      } else if (this.is_LABEL_START()) {
+        const tok = this.consume_VARIABLE();
+        return tok;
+      }
+    } else if (ch === "{") {
+      if (this._input[this.offset] === "$") {
+        this.begin("ST_IN_SCRIPTING");
+        return this.tok.T_CURLY_OPEN;
+      }
+    } else if (ch === '"') {
+      this.popState();
+      return '"';
+    }
+
+    // any char
+    while (this.offset < this.size) {
+      if (ch === "\\") {
+        this.input();
+      } else if (ch === '"') {
+        this.unput(1);
+        this.popState();
+        this.appendToken('"', 1);
+        break;
+      } else if (ch === "$") {
+        ch = this.input();
+        if (ch === "{") {
+          this.begin("ST_LOOKING_FOR_VARNAME");
+          if (this.yytext.length > 2) {
+            this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2);
+            this.unput(2);
+            return this.tok.T_ENCAPSED_AND_WHITESPACE;
+          } else {
+            return this.tok.T_DOLLAR_OPEN_CURLY_BRACES;
+          }
+        } else if (this.is_LABEL_START()) {
+          // start of $var...
+          const yyoffset = this.offset;
+          const next = this.consume_VARIABLE();
+          if (this.yytext.length > this.offset - yyoffset + 2) {
+            this.appendToken(next, this.offset - yyoffset + 2);
+            this.unput(this.offset - yyoffset + 2);
+            return this.tok.T_ENCAPSED_AND_WHITESPACE;
+          } else {
+            return next;
+          }
+        }
+        if (ch) this.unput(1);
+      } else if (ch === "{") {
+        ch = this.input();
+        if (ch === "$") {
+          // start of {$...
+          this.begin("ST_IN_SCRIPTING");
+          if (this.yytext.length > 2) {
+            this.appendToken(this.tok.T_CURLY_OPEN, 1);
+            this.unput(2);
+            return this.tok.T_ENCAPSED_AND_WHITESPACE;
+          } else {
+            // @fixme : yytext = '"{$' (this.yytext.length > 3)
+            this.unput(1);
+            return this.tok.T_CURLY_OPEN;
+          }
+        }
+        if (ch) this.unput(1);
+      }
+      ch = this.input();
+    }
+    return this.tok.T_ENCAPSED_AND_WHITESPACE;
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser.html b/docs/parser.html new file mode 100644 index 000000000..810d0b376 --- /dev/null +++ b/docs/parser.html @@ -0,0 +1,1593 @@ + + + + + + + + + parser - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser +

+ + + + +
+
+ +

+ + parser + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new parser() +

+
+ + + + + +
+

The PHP Parser class that build the AST tree from the lexer

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
lexer + + + + Lexer + + + + + + + +

current lexer instance

+
ast + + + + AST + + + + + + + +

the AST factory instance

+
token + + + + Integer + + + | + + + String + + + + + + + +

current token

+
extractDoc + + + + Boolean + + + + + + + +

should extract documentation as AST node

+
extractTokens + + + + Boolean + + + + + + + +

should extract each token

+
suppressErrors + + + + Boolean + + + + + + + +

should ignore parsing errors and continue

+
debug + + + + Boolean + + + + + + + +

should output debug informations

+
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + +
Tutorials:
+
+ +
+ + + + + +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ error() +

+
+ + + + + +
+

handling errors

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ expect(token) → {boolean} +

+
+ + + + + +
+

Force the parser to check the current token.

+

If the current token does not match to expected token, +the an error will be raised.

+

If the suppressError mode is activated, then the error will +be added to the program error stack and this function will return false.

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
token + + + + String + + + | + + + Number + + + + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + +
Throws:
+ + + +
+ +

Error

+ +
+ + + + + + + + + + + + + + + + + + +

+ expectEndOfStatement() → {boolean} +

+
+ + + + + +
+

expects an end of statement or end of file

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ getTokenName() +

+
+ + + + + +
+

helper : gets a token name

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ is() +

+
+ + + + + +
+

Check if token is of specified type

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ lex() +

+
+ + + + + +
+

Eating a token

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ next() +

+
+ + + + + +
+

consume the next token

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ node() +

+
+ + + + + +
+

Creates a new AST node

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ parse() +

+
+ + + + + +
+

main entry point : converts a source code to AST

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ raiseError() +

+
+ + + + + +
+

Raise an error

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ text() → {String} +

+
+ + + + + +
+

Returns the current token contents

+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/parser.js.html b/docs/parser.js.html new file mode 100644 index 000000000..78e798fa6 --- /dev/null +++ b/docs/parser.js.html @@ -0,0 +1,804 @@ + + + + + + + + + + + parser.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+/**
+ * @private
+ */
+function isNumber(n) {
+  return n != "." && n != "," && !isNaN(parseFloat(n)) && isFinite(n);
+}
+
+/**
+ * The PHP Parser class that build the AST tree from the lexer
+ *
+ * @class
+ * @tutorial Parser
+ * @property {Lexer} lexer - current lexer instance
+ * @property {AST} ast - the AST factory instance
+ * @property {Integer|String} token - current token
+ * @property {Boolean} extractDoc - should extract documentation as AST node
+ * @property {Boolean} extractTokens - should extract each token
+ * @property {Boolean} suppressErrors - should ignore parsing errors and continue
+ * @property {Boolean} debug - should output debug informations
+ */
+const parser = function(lexer, ast) {
+  this.lexer = lexer;
+  this.ast = ast;
+  this.tok = lexer.tok;
+  this.EOF = lexer.EOF;
+  this.token = null;
+  this.prev = null;
+  this.debug = false;
+  this.php7 = true;
+  this.php74 = true;
+  this.extractDoc = false;
+  this.extractTokens = false;
+  this.suppressErrors = false;
+  const mapIt = function(item) {
+    return [item, null];
+  };
+  this.entries = {
+    IDENTIFIER: new Map(
+      [
+        this.tok.T_ABSTRACT,
+        this.tok.T_ARRAY,
+        this.tok.T_AS,
+        this.tok.T_BREAK,
+        this.tok.T_CALLABLE,
+        this.tok.T_CASE,
+        this.tok.T_CATCH,
+        this.tok.T_CLASS,
+        this.tok.T_CLASS_C,
+        this.tok.T_CLONE,
+        this.tok.T_CONST,
+        this.tok.T_CONTINUE,
+        this.tok.T_DECLARE,
+        this.tok.T_DEFAULT,
+        this.tok.T_DIR,
+        this.tok.T_DO,
+        this.tok.T_ECHO,
+        this.tok.T_ELSE,
+        this.tok.T_ELSEIF,
+        this.tok.T_EMPTY,
+        this.tok.T_ENDDECLARE,
+        this.tok.T_ENDFOR,
+        this.tok.T_ENDFOREACH,
+        this.tok.T_ENDIF,
+        this.tok.T_ENDSWITCH,
+        this.tok.T_ENDWHILE,
+        this.tok.T_EVAL,
+        this.tok.T_EXIT,
+        this.tok.T_EXTENDS,
+        this.tok.T_FILE,
+        this.tok.T_FINAL,
+        this.tok.T_FINALLY,
+        this.tok.T_FUNC_C,
+        this.tok.T_FOR,
+        this.tok.T_FOREACH,
+        this.tok.T_FUNCTION,
+        this.tok.T_GLOBAL,
+        this.tok.T_GOTO,
+        this.tok.T_IF,
+        this.tok.T_IMPLEMENTS,
+        this.tok.T_INCLUDE,
+        this.tok.T_INCLUDE_ONCE,
+        this.tok.T_INSTANCEOF,
+        this.tok.T_INSTEADOF,
+        this.tok.T_INTERFACE,
+        this.tok.T_ISSET,
+        this.tok.T_LINE,
+        this.tok.T_LIST,
+        this.tok.T_LOGICAL_AND,
+        this.tok.T_LOGICAL_OR,
+        this.tok.T_LOGICAL_XOR,
+        this.tok.T_METHOD_C,
+        this.tok.T_NAMESPACE,
+        this.tok.T_NEW,
+        this.tok.T_NS_C,
+        this.tok.T_PRINT,
+        this.tok.T_PRIVATE,
+        this.tok.T_PROTECTED,
+        this.tok.T_PUBLIC,
+        this.tok.T_REQUIRE,
+        this.tok.T_REQUIRE_ONCE,
+        this.tok.T_RETURN,
+        this.tok.T_STATIC,
+        this.tok.T_SWITCH,
+        this.tok.T_THROW,
+        this.tok.T_TRAIT,
+        this.tok.T_TRY,
+        this.tok.T_UNSET,
+        this.tok.T_USE,
+        this.tok.T_VAR,
+        this.tok.T_WHILE,
+        this.tok.T_YIELD
+      ].map(mapIt)
+    ),
+    VARIABLE: new Map(
+      [
+        this.tok.T_VARIABLE,
+        "$",
+        "&",
+        this.tok.T_NS_SEPARATOR,
+        this.tok.T_STRING,
+        this.tok.T_NAMESPACE,
+        this.tok.T_STATIC
+      ].map(mapIt)
+    ),
+    SCALAR: new Map(
+      [
+        this.tok.T_CONSTANT_ENCAPSED_STRING,
+        this.tok.T_START_HEREDOC,
+        this.tok.T_LNUMBER,
+        this.tok.T_DNUMBER,
+        this.tok.T_ARRAY,
+        "[",
+        this.tok.T_CLASS_C,
+        this.tok.T_TRAIT_C,
+        this.tok.T_FUNC_C,
+        this.tok.T_METHOD_C,
+        this.tok.T_LINE,
+        this.tok.T_FILE,
+        this.tok.T_DIR,
+        this.tok.T_NS_C,
+        '"',
+        'b"',
+        'B"',
+        "-",
+        this.tok.T_NS_SEPARATOR
+      ].map(mapIt)
+    ),
+    T_MAGIC_CONST: new Map(
+      [
+        this.tok.T_CLASS_C,
+        this.tok.T_TRAIT_C,
+        this.tok.T_FUNC_C,
+        this.tok.T_METHOD_C,
+        this.tok.T_LINE,
+        this.tok.T_FILE,
+        this.tok.T_DIR,
+        this.tok.T_NS_C
+      ].map(mapIt)
+    ),
+    T_MEMBER_FLAGS: new Map(
+      [
+        this.tok.T_PUBLIC,
+        this.tok.T_PRIVATE,
+        this.tok.T_PROTECTED,
+        this.tok.T_STATIC,
+        this.tok.T_ABSTRACT,
+        this.tok.T_FINAL
+      ].map(mapIt)
+    ),
+    EOS: new Map([";", this.EOF, this.tok.T_INLINE_HTML].map(mapIt)),
+    EXPR: new Map(
+      [
+        "@",
+        "-",
+        "+",
+        "!",
+        "~",
+        "(",
+        "`",
+        this.tok.T_LIST,
+        this.tok.T_CLONE,
+        this.tok.T_INC,
+        this.tok.T_DEC,
+        this.tok.T_NEW,
+        this.tok.T_ISSET,
+        this.tok.T_EMPTY,
+        this.tok.T_INCLUDE,
+        this.tok.T_INCLUDE_ONCE,
+        this.tok.T_REQUIRE,
+        this.tok.T_REQUIRE_ONCE,
+        this.tok.T_EVAL,
+        this.tok.T_INT_CAST,
+        this.tok.T_DOUBLE_CAST,
+        this.tok.T_STRING_CAST,
+        this.tok.T_ARRAY_CAST,
+        this.tok.T_OBJECT_CAST,
+        this.tok.T_BOOL_CAST,
+        this.tok.T_UNSET_CAST,
+        this.tok.T_EXIT,
+        this.tok.T_PRINT,
+        this.tok.T_YIELD,
+        this.tok.T_STATIC,
+        this.tok.T_FUNCTION,
+        // using VARIABLES :
+        this.tok.T_VARIABLE,
+        "$",
+        this.tok.T_NS_SEPARATOR,
+        this.tok.T_STRING,
+        // using SCALAR :
+        this.tok.T_STRING, // @see variable.js line 45 > conflict with variable = shift/reduce :)
+        this.tok.T_CONSTANT_ENCAPSED_STRING,
+        this.tok.T_START_HEREDOC,
+        this.tok.T_LNUMBER,
+        this.tok.T_DNUMBER,
+        this.tok.T_ARRAY,
+        "[",
+        this.tok.T_CLASS_C,
+        this.tok.T_TRAIT_C,
+        this.tok.T_FUNC_C,
+        this.tok.T_METHOD_C,
+        this.tok.T_LINE,
+        this.tok.T_FILE,
+        this.tok.T_DIR,
+        this.tok.T_NS_C
+      ].map(mapIt)
+    )
+  };
+};
+
+/**
+ * helper : gets a token name
+ */
+parser.prototype.getTokenName = function(token) {
+  if (!isNumber(token)) {
+    return "'" + token + "'";
+  } else {
+    if (token == this.EOF) return "the end of file (EOF)";
+    return this.lexer.engine.tokens.values[token];
+  }
+};
+
+/**
+ * main entry point : converts a source code to AST
+ */
+parser.prototype.parse = function(code, filename) {
+  this._errors = [];
+  this.filename = filename || "eval";
+  this.currentNamespace = [""];
+  if (this.extractDoc) {
+    this._docs = [];
+  } else {
+    this._docs = null;
+  }
+  if (this.extractTokens) {
+    this._tokens = [];
+  } else {
+    this._tokens = null;
+  }
+  if (!this.php7) {
+    this.php74 = false;
+  }
+  this._docIndex = 0;
+  this._lastNode = null;
+  this.lexer.setInput(code);
+  this.lexer.all_tokens = this.extractTokens;
+  this.lexer.comment_tokens = this.extractDoc;
+  this.length = this.lexer._input.length;
+  this.innerList = false;
+  this.innerListForm = false;
+  const program = this.node("program");
+  let childs = [];
+  this.next();
+  while (this.token != this.EOF) {
+    const node = this.read_start();
+    if (node !== null && node !== undefined) {
+      if (Array.isArray(node)) {
+        childs = childs.concat(node);
+      } else {
+        childs.push(node);
+      }
+    }
+  }
+  // #176 : register latest position
+  this.prev = [
+    this.lexer.yylloc.last_line,
+    this.lexer.yylloc.last_column,
+    this.lexer.offset
+  ];
+  const result = program(childs, this._errors, this._docs, this._tokens);
+  if (this.debug) {
+    const errors = this.ast.checkNodes();
+    if (errors.length > 0) {
+      errors.forEach(function(error) {
+        if (error.position) {
+          // eslint-disable-next-line no-console
+          console.log(
+            "Node at line " +
+              error.position.line +
+              ", column " +
+              error.position.column
+          );
+        }
+        // eslint-disable-next-line no-console
+        console.log(error.stack.join("\n"));
+      });
+      throw new Error("Some nodes are not closed");
+    }
+  }
+  return result;
+};
+
+/**
+ * Raise an error
+ */
+parser.prototype.raiseError = function(message, msgExpect, expect, token) {
+  message += " on line " + this.lexer.yylloc.first_line;
+  if (!this.suppressErrors) {
+    const err = new SyntaxError(
+      message,
+      this.filename,
+      this.lexer.yylloc.first_line
+    );
+    err.lineNumber = this.lexer.yylloc.first_line;
+    err.fileName = this.filename;
+    err.columnNumber = this.lexer.yylloc.first_column;
+    throw err;
+  }
+  // Error node :
+  const node = this.ast.prepare("error", null, this)(
+    message,
+    token,
+    this.lexer.yylloc.first_line,
+    expect
+  );
+  this._errors.push(node);
+  return node;
+};
+
+/**
+ * handling errors
+ */
+parser.prototype.error = function(expect) {
+  let msg = "Parse Error : syntax error";
+  let token = this.getTokenName(this.token);
+  let msgExpect = "";
+
+  if (this.token !== this.EOF) {
+    if (isNumber(this.token)) {
+      let symbol = this.text();
+      if (symbol.length > 10) {
+        symbol = symbol.substring(0, 7) + "...";
+      }
+      token = "'" + symbol + "' (" + token + ")";
+    }
+    msg += ", unexpected " + token;
+  }
+  if (expect && !Array.isArray(expect)) {
+    if (isNumber(expect) || expect.length === 1) {
+      msgExpect = ", expecting " + this.getTokenName(expect);
+    }
+    msg += msgExpect;
+  }
+  return this.raiseError(msg, msgExpect, expect, token);
+};
+
+/**
+ * Creates a new AST node
+ */
+parser.prototype.node = function(name) {
+  if (this.extractDoc) {
+    let docs = null;
+    if (this._docIndex < this._docs.length) {
+      docs = this._docs.slice(this._docIndex);
+      this._docIndex = this._docs.length;
+      if (this.debug) {
+        // eslint-disable-next-line no-console
+        console.log(new Error("Append docs on " + name));
+        // eslint-disable-next-line no-console
+        console.log(docs);
+      }
+    }
+    const node = this.ast.prepare(name, docs, this);
+    /**
+     * TOKENS :
+     * node1 commentA token commmentB node2 commentC token commentD node3 commentE token
+     *
+     * AST :
+     * structure:S1 [
+     *    left: node1 ( trail: commentA ),
+     *    right: structure:S2 [
+     *       node2 (lead: commentB, trail: commentC),
+     *       node3 (lead: commentD)
+     *    ],
+     *    trail: commentE
+     * ]
+     *
+     * Algorithm :
+     *
+     * Attach the last comments on parent of current node
+     * If a new node is started and the parent has a trailing comment
+     * the move it on previous node
+     *
+     * start S2
+     * start node1
+     * consume node1 & set commentA as trailingComment on S2
+     * start S2
+     * S1 has a trailingComment, attach it on node1
+     * ...
+     * NOTE : As the trailingComment Behavior depends on AST, it will be build on
+     * the AST layer - last child node will keep it's trailingComment nodes
+     */
+    node.postBuild = function(self) {
+      if (this._docIndex < this._docs.length) {
+        if (this._lastNode) {
+          const offset = this.prev[2];
+          let max = this._docIndex;
+          for (; max < this._docs.length; max++) {
+            if (this._docs[max].offset > offset) {
+              break;
+            }
+          }
+          if (max > this._docIndex) {
+            // inject trailing comment on child node
+            this._lastNode.setTrailingComments(
+              this._docs.slice(this._docIndex, max)
+            );
+            this._docIndex = max;
+          }
+        } else if (this.token === this.EOF) {
+          // end of content
+          self.setTrailingComments(this._docs.slice(this._docIndex));
+          this._docIndex = this._docs.length;
+        }
+      }
+      this._lastNode = self;
+    }.bind(this);
+    return node;
+  }
+  return this.ast.prepare(name, null, this);
+};
+
+/**
+ * expects an end of statement or end of file
+ * @return {boolean}
+ */
+parser.prototype.expectEndOfStatement = function(node) {
+  if (this.token === ";") {
+    // include only real ';' statements
+    // https://github.com/glayzzle/php-parser/issues/164
+    if (node && this.lexer.yytext === ";") {
+      node.includeToken(this);
+    }
+  } else if (this.token !== this.tok.T_INLINE_HTML && this.token !== this.EOF) {
+    this.error(";");
+    return false;
+  }
+  this.next();
+  return true;
+};
+
+/** outputs some debug information on current token **/
+const ignoreStack = ["parser.next", "parser.node", "parser.showlog"];
+parser.prototype.showlog = function() {
+  const stack = new Error().stack.split("\n");
+  let line;
+  for (let offset = 2; offset < stack.length; offset++) {
+    line = stack[offset].trim();
+    let found = false;
+    for (let i = 0; i < ignoreStack.length; i++) {
+      if (line.substring(3, 3 + ignoreStack[i].length) === ignoreStack[i]) {
+        found = true;
+        break;
+      }
+    }
+    if (!found) {
+      break;
+    }
+  }
+  // eslint-disable-next-line no-console
+  console.log(
+    "Line " +
+      this.lexer.yylloc.first_line +
+      " : " +
+      this.getTokenName(this.token) +
+      ">" +
+      this.lexer.yytext +
+      "<" +
+      " @-->" +
+      line
+  );
+  return this;
+};
+
+/**
+ * Force the parser to check the current token.
+ *
+ * If the current token does not match to expected token,
+ * the an error will be raised.
+ *
+ * If the suppressError mode is activated, then the error will
+ * be added to the program error stack and this function will return `false`.
+ *
+ * @param {String|Number} token
+ * @return {boolean}
+ * @throws Error
+ */
+parser.prototype.expect = function(token) {
+  if (Array.isArray(token)) {
+    if (token.indexOf(this.token) === -1) {
+      this.error(token);
+      return false;
+    }
+  } else if (this.token != token) {
+    this.error(token);
+    return false;
+  }
+  return true;
+};
+
+/**
+ * Returns the current token contents
+ * @return {String}
+ */
+parser.prototype.text = function() {
+  return this.lexer.yytext;
+};
+
+/** consume the next token **/
+parser.prototype.next = function() {
+  // prepare the back command
+  if (this.token !== ";" || this.lexer.yytext === ";") {
+    // ignore '?>' from automated resolution
+    // https://github.com/glayzzle/php-parser/issues/168
+    this.prev = [
+      this.lexer.yylloc.last_line,
+      this.lexer.yylloc.last_column,
+      this.lexer.offset
+    ];
+  }
+
+  // eating the token
+  this.lex();
+
+  // showing the debug
+  if (this.debug) {
+    this.showlog();
+  }
+
+  // handling comments
+  if (this.extractDoc) {
+    while (
+      this.token === this.tok.T_COMMENT ||
+      this.token === this.tok.T_DOC_COMMENT
+    ) {
+      // APPEND COMMENTS
+      if (this.token === this.tok.T_COMMENT) {
+        this._docs.push(this.read_comment());
+      } else {
+        this._docs.push(this.read_doc_comment());
+      }
+    }
+  }
+
+  return this;
+};
+
+/**
+ * Eating a token
+ */
+parser.prototype.lex = function() {
+  // append on token stack
+  if (this.extractTokens) {
+    do {
+      // the token
+      this.token = this.lexer.lex() || this.EOF;
+      if (this.token === this.EOF) return this;
+      let entry = this.lexer.yytext;
+      if (this.lexer.engine.tokens.values.hasOwnProperty(this.token)) {
+        entry = [
+          this.lexer.engine.tokens.values[this.token],
+          entry,
+          this.lexer.yylloc.first_line,
+          this.lexer.yylloc.first_offset,
+          this.lexer.offset
+        ];
+      } else {
+        entry = [
+          null,
+          entry,
+          this.lexer.yylloc.first_line,
+          this.lexer.yylloc.first_offset,
+          this.lexer.offset
+        ];
+      }
+      this._tokens.push(entry);
+      if (this.token === this.tok.T_CLOSE_TAG) {
+        // https://github.com/php/php-src/blob/7ff186434e82ee7be7c59d0db9a976641cf7b09c/Zend/zend_compile.c#L1680
+        this.token = ";";
+        return this;
+      } else if (this.token === this.tok.T_OPEN_TAG_WITH_ECHO) {
+        this.token = this.tok.T_ECHO;
+        return this;
+      }
+    } while (
+      this.token === this.tok.T_WHITESPACE || // ignore white space
+      (!this.extractDoc &&
+        (this.token === this.tok.T_COMMENT || // ignore single lines comments
+          this.token === this.tok.T_DOC_COMMENT)) || // ignore doc comments
+      // ignore open tags
+      this.token === this.tok.T_OPEN_TAG
+    );
+  } else {
+    this.token = this.lexer.lex() || this.EOF;
+  }
+  return this;
+};
+
+/**
+ * Check if token is of specified type
+ */
+parser.prototype.is = function(type) {
+  if (Array.isArray(type)) {
+    return type.indexOf(this.token) !== -1;
+  }
+  return this.entries[type].has(this.token);
+};
+
+// extends the parser with syntax files
+[
+  require("./parser/array.js"),
+  require("./parser/class.js"),
+  require("./parser/comment.js"),
+  require("./parser/expr.js"),
+  require("./parser/function.js"),
+  require("./parser/if.js"),
+  require("./parser/loops.js"),
+  require("./parser/main.js"),
+  require("./parser/namespace.js"),
+  require("./parser/scalar.js"),
+  require("./parser/statement.js"),
+  require("./parser/switch.js"),
+  require("./parser/try.js"),
+  require("./parser/utils.js"),
+  require("./parser/variable.js")
+].forEach(function(ext) {
+  for (const k in ext) {
+    if (parser.prototype.hasOwnProperty(k)) {
+      // @see https://github.com/glayzzle/php-parser/issues/234
+      throw new Error("Function " + k + " is already defined - collision");
+    }
+    parser.prototype[k] = ext[k];
+  }
+});
+
+module.exports = parser;
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_array.js.html b/docs/parser_array.js.html new file mode 100644 index 000000000..62e86650a --- /dev/null +++ b/docs/parser_array.js.html @@ -0,0 +1,232 @@ + + + + + + + + + + + parser/array.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/array.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const ArrayExpr = "array";
+const ArrayEntry = "entry";
+
+module.exports = {
+  /**
+   * Parse an array
+   * ```ebnf
+   * array ::= T_ARRAY '(' array_pair_list ')' |
+   *   '[' array_pair_list ']'
+   * ```
+   */
+  read_array: function() {
+    let expect = null;
+    let shortForm = false;
+    const result = this.node(ArrayExpr);
+
+    if (this.token === this.tok.T_ARRAY) {
+      this.next().expect("(");
+      expect = ")";
+    } else {
+      shortForm = true;
+      expect = "]";
+    }
+    let items = [];
+    if (this.next().token !== expect) {
+      items = this.read_array_pair_list(shortForm);
+    }
+    this.expect(expect);
+    this.next();
+    return result(shortForm, items);
+  },
+  /**
+   * Reads an array of items
+   * ```ebnf
+   * array_pair_list ::= array_pair (',' array_pair?)*
+   * ```
+   */
+  read_array_pair_list: function(shortForm) {
+    const self = this;
+    return this.read_list(
+      function() {
+        return self.read_array_pair(shortForm);
+      },
+      ",",
+      true
+    );
+  },
+  /**
+   * Reads an entry
+   * array_pair:
+   *  expr T_DOUBLE_ARROW expr
+   *  | expr
+   *  | expr T_DOUBLE_ARROW '&' variable
+   *  | '&' variable
+   *  | expr T_DOUBLE_ARROW T_LIST '(' array_pair_list ')'
+   *  | T_LIST '(' array_pair_list ')'
+   */
+  read_array_pair: function(shortForm) {
+    if (
+      this.token === "," ||
+      (!shortForm && this.token === ")") ||
+      (shortForm && this.token === "]")
+    ) {
+      return this.node("noop")();
+    }
+    if (this.token === "&") {
+      return this.next().read_variable(true, false, true);
+    } else {
+      const entry = this.node(ArrayEntry);
+      const expr = this.read_expr();
+      if (this.token === this.tok.T_DOUBLE_ARROW) {
+        if (this.next().token === "&") {
+          return entry(expr, this.next().read_variable(true, false, true));
+        } else {
+          return entry(expr, this.read_expr());
+        }
+      } else {
+        entry.destroy();
+      }
+      return expr;
+    }
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_class.js.html b/docs/parser_class.js.html new file mode 100644 index 000000000..2e0cba3e9 --- /dev/null +++ b/docs/parser_class.js.html @@ -0,0 +1,625 @@ + + + + + + + + + + + parser/class.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/class.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * reading a class
+   * ```ebnf
+   * class ::= class_scope? T_CLASS T_STRING (T_EXTENDS NAMESPACE_NAME)? (T_IMPLEMENTS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' CLASS_BODY '}'
+   * ```
+   */
+  read_class: function() {
+    const result = this.node("class");
+    const flag = this.read_class_scope();
+    // graceful mode : ignore token & go next
+    if (this.token !== this.tok.T_CLASS) {
+      this.error(this.tok.T_CLASS);
+      this.next();
+      return null;
+    }
+    this.next().expect(this.tok.T_STRING);
+    let propName = this.node("identifier");
+    const name = this.text();
+    this.next();
+    propName = propName(name);
+    let propExtends = null;
+    if (this.token == this.tok.T_EXTENDS) {
+      propExtends = this.next().read_namespace_name();
+    }
+    let propImplements = null;
+    if (this.token == this.tok.T_IMPLEMENTS) {
+      propImplements = this.next().read_name_list();
+    }
+    this.expect("{");
+    const body = this.next().read_class_body();
+    return result(propName, propExtends, propImplements, body, flag);
+  },
+  /**
+   * Read the class visibility
+   * ```ebnf
+   *   class_scope ::= (T_FINAL | T_ABSTRACT)?
+   * ```
+   */
+  read_class_scope: function() {
+    const result = this.token;
+    if (result == this.tok.T_FINAL) {
+      this.next();
+      return [0, 0, 2];
+    } else if (result == this.tok.T_ABSTRACT) {
+      this.next();
+      return [0, 0, 1];
+    }
+    return [0, 0, 0];
+  },
+  /**
+   * Reads a class body
+   * ```ebnf
+   *   class_body ::= (member_flags? (T_VAR | T_STRING | T_FUNCTION))*
+   * ```
+   */
+  read_class_body: function() {
+    let result = [];
+
+    while (this.token !== this.EOF && this.token !== "}") {
+      if (this.token === this.tok.T_COMMENT) {
+        result.push(this.read_comment());
+        continue;
+      }
+
+      if (this.token === this.tok.T_DOC_COMMENT) {
+        result.push(this.read_doc_comment());
+        continue;
+      }
+
+      // check T_USE trait
+      if (this.token === this.tok.T_USE) {
+        result = result.concat(this.read_trait_use_statement());
+        continue;
+      }
+
+      // read member flags
+      const flags = this.read_member_flags(false);
+
+      // check constant
+      if (this.token === this.tok.T_CONST) {
+        const constants = this.read_constant_list(flags);
+        if (this.expect(";")) {
+          this.next();
+        }
+        result = result.concat(constants);
+        continue;
+      }
+
+      // jump over T_VAR then land on T_VARIABLE
+      if (this.token === this.tok.T_VAR) {
+        this.next().expect(this.tok.T_VARIABLE);
+        flags[0] = null; // public (as null)
+        flags[1] = 0; // non static var
+      }
+
+      if (this.token === this.tok.T_VARIABLE) {
+        // reads a variable
+        const variables = this.read_variable_list(flags);
+        this.expect(";");
+        this.next();
+        result = result.concat(variables);
+      } else if (this.token === this.tok.T_FUNCTION) {
+        // reads a function
+        result.push(this.read_function(false, flags));
+      } else {
+        // raise an error
+        this.error([
+          this.tok.T_CONST,
+          this.tok.T_VARIABLE,
+          this.tok.T_FUNCTION
+        ]);
+        // ignore token
+        this.next();
+      }
+    }
+    this.expect("}");
+    this.next();
+    return result;
+  },
+  /**
+   * Reads variable list
+   * ```ebnf
+   *  variable_list ::= (variable_declaration ',')* variable_declaration
+   * ```
+   */
+  read_variable_list: function(flags) {
+    const result = this.node("propertystatement");
+
+    const properties = this.read_list(
+      /**
+       * Reads a variable declaration
+       *
+       * ```ebnf
+       *  variable_declaration ::= T_VARIABLE '=' scalar
+       * ```
+       */
+      function read_variable_declaration() {
+        const result = this.node("property");
+        this.expect(this.tok.T_VARIABLE);
+        let propName = this.node("identifier");
+        const name = this.text().substring(1); // ignore $
+        this.next();
+        propName = propName(name);
+        if (this.token === ";" || this.token === ",") {
+          return result(propName, null);
+        } else if (this.token === "=") {
+          // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L815
+          return result(propName, this.next().read_expr());
+        } else {
+          this.expect([",", ";", "="]);
+          return result(propName, null);
+        }
+      },
+      ","
+    );
+
+    return result(null, properties, flags);
+  },
+  /**
+   * Reads constant list
+   * ```ebnf
+   *  constant_list ::= T_CONST (constant_declaration ',')* constant_declaration
+   * ```
+   */
+  read_constant_list: function(flags) {
+    if (this.expect(this.tok.T_CONST)) {
+      this.next();
+    }
+    const result = this.node("classconstant");
+    const items = this.read_list(
+      /**
+       * Reads a constant declaration
+       *
+       * ```ebnf
+       *  constant_declaration ::= (T_STRING | IDENTIFIER) '=' expr
+       * ```
+       * @return {Constant} [:link:](AST.md#constant)
+       */
+      function read_constant_declaration() {
+        const result = this.node("constant");
+        let constName = null;
+        let value = null;
+        if (
+          this.token === this.tok.T_STRING ||
+          (this.php7 && this.is("IDENTIFIER"))
+        ) {
+          constName = this.node("identifier");
+          const name = this.text();
+          this.next();
+          constName = constName(name);
+        } else {
+          this.expect("IDENTIFIER");
+        }
+        if (this.expect("=")) {
+          value = this.next().read_expr();
+        }
+        return result(constName, value);
+      },
+      ","
+    );
+
+    return result(null, items, flags);
+  },
+  /**
+   * Read member flags
+   * @return array
+   *  1st index : 0 => public, 1 => protected, 2 => private
+   *  2nd index : 0 => instance member, 1 => static member
+   *  3rd index : 0 => normal, 1 => abstract member, 2 => final member
+   */
+  read_member_flags: function(asInterface) {
+    const result = [-1, -1, -1];
+    if (this.is("T_MEMBER_FLAGS")) {
+      let idx = 0,
+        val = 0;
+      do {
+        switch (this.token) {
+          case this.tok.T_PUBLIC:
+            idx = 0;
+            val = 0;
+            break;
+          case this.tok.T_PROTECTED:
+            idx = 0;
+            val = 1;
+            break;
+          case this.tok.T_PRIVATE:
+            idx = 0;
+            val = 2;
+            break;
+          case this.tok.T_STATIC:
+            idx = 1;
+            val = 1;
+            break;
+          case this.tok.T_ABSTRACT:
+            idx = 2;
+            val = 1;
+            break;
+          case this.tok.T_FINAL:
+            idx = 2;
+            val = 2;
+            break;
+        }
+        if (asInterface) {
+          if (idx == 0 && val == 2) {
+            // an interface can't be private
+            this.expect([this.tok.T_PUBLIC, this.tok.T_PROTECTED]);
+            val = -1;
+          } else if (idx == 2 && val == 1) {
+            // an interface cant be abstract
+            this.error();
+            val = -1;
+          }
+        }
+        if (result[idx] !== -1) {
+          // already defined flag
+          this.error();
+        } else if (val !== -1) {
+          result[idx] = val;
+        }
+      } while (this.next().is("T_MEMBER_FLAGS"));
+    }
+
+    if (result[1] == -1) result[1] = 0;
+    if (result[2] == -1) result[2] = 0;
+    return result;
+  },
+  /**
+   * reading an interface
+   * ```ebnf
+   * interface ::= T_INTERFACE T_STRING (T_EXTENDS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' INTERFACE_BODY '}'
+   * ```
+   */
+  read_interface: function() {
+    const result = this.node("interface");
+    if (this.token !== this.tok.T_INTERFACE) {
+      this.error(this.tok.T_INTERFACE);
+      this.next();
+      return null;
+    }
+    this.next().expect(this.tok.T_STRING);
+    let propName = this.node("identifier");
+    const name = this.text();
+    this.next();
+    propName = propName(name);
+    let propExtends = null;
+    if (this.token === this.tok.T_EXTENDS) {
+      propExtends = this.next().read_name_list();
+    }
+    this.expect("{");
+    const body = this.next().read_interface_body();
+    return result(propName, propExtends, body);
+  },
+  /**
+   * Reads an interface body
+   * ```ebnf
+   *   interface_body ::= (member_flags? (T_CONST | T_FUNCTION))*
+   * ```
+   */
+  read_interface_body: function() {
+    let result = [];
+
+    while (this.token !== this.EOF && this.token !== "}") {
+      if (this.token === this.tok.T_COMMENT) {
+        result.push(this.read_comment());
+        continue;
+      }
+
+      if (this.token === this.tok.T_DOC_COMMENT) {
+        result.push(this.read_doc_comment());
+        continue;
+      }
+
+      // read member flags
+      const flags = this.read_member_flags(true);
+
+      // check constant
+      if (this.token == this.tok.T_CONST) {
+        const constants = this.read_constant_list(flags);
+        if (this.expect(";")) {
+          this.next();
+        }
+        result = result.concat(constants);
+      } else if (this.token === this.tok.T_FUNCTION) {
+        // reads a function
+        const method = this.read_function_declaration(2, flags);
+        method.parseFlags(flags);
+        result.push(method);
+        if (this.expect(";")) {
+          this.next();
+        }
+      } else {
+        // raise an error
+        this.error([this.tok.T_CONST, this.tok.T_FUNCTION]);
+        this.next();
+      }
+    }
+    if (this.expect("}")) {
+      this.next();
+    }
+    return result;
+  },
+  /**
+   * reading a trait
+   * ```ebnf
+   * trait ::= T_TRAIT T_STRING (T_EXTENDS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' FUNCTION* '}'
+   * ```
+   */
+  read_trait: function() {
+    const result = this.node("trait");
+    // graceful mode : ignore token & go next
+    if (this.token !== this.tok.T_TRAIT) {
+      this.error(this.tok.T_TRAIT);
+      this.next();
+      return null;
+    }
+    this.next().expect(this.tok.T_STRING);
+    let propName = this.node("identifier");
+    const name = this.text();
+    this.next();
+    propName = propName(name);
+    this.expect("{");
+    const body = this.next().read_class_body();
+    return result(propName, body);
+  },
+  /**
+   * reading a use statement
+   * ```ebnf
+   * trait_use_statement ::= namespace_name (',' namespace_name)* ('{' trait_use_alias '}')?
+   * ```
+   */
+  read_trait_use_statement: function() {
+    // defines use statements
+    const node = this.node("traituse");
+    this.expect(this.tok.T_USE) && this.next();
+    const traits = [this.read_namespace_name()];
+    let adaptations = null;
+    while (this.token === ",") {
+      traits.push(this.next().read_namespace_name());
+    }
+    if (this.token === "{") {
+      adaptations = [];
+      // defines alias statements
+      while (this.next().token !== this.EOF) {
+        if (this.token === "}") break;
+        adaptations.push(this.read_trait_use_alias());
+        this.expect(";");
+      }
+      if (this.expect("}")) {
+        this.next();
+      }
+    } else {
+      if (this.expect(";")) {
+        this.next();
+      }
+    }
+    return node(traits, adaptations);
+  },
+  /**
+   * Reading trait alias
+   * ```ebnf
+   * trait_use_alias ::= namespace_name ( T_DOUBLE_COLON T_STRING )? (T_INSTEADOF namespace_name) | (T_AS member_flags? T_STRING)
+   * ```
+   * name list : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L303
+   * trait adaptation : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L742
+   */
+  read_trait_use_alias: function() {
+    const node = this.node();
+    let trait = null;
+    let method;
+
+    if (this.is("IDENTIFIER")) {
+      method = this.node("identifier");
+      const methodName = this.text();
+      this.next();
+      method = method(methodName);
+    } else {
+      method = this.read_namespace_name();
+
+      if (this.token === this.tok.T_DOUBLE_COLON) {
+        this.next();
+        if (
+          this.token === this.tok.T_STRING ||
+          (this.php7 && this.is("IDENTIFIER"))
+        ) {
+          trait = method;
+          method = this.node("identifier");
+          const methodName = this.text();
+          this.next();
+          method = method(methodName);
+        } else {
+          this.expect(this.tok.T_STRING);
+        }
+      } else {
+        // convert identifier as string
+        method = method.name;
+      }
+    }
+
+    // handle trait precedence
+    if (this.token === this.tok.T_INSTEADOF) {
+      return node(
+        "traitprecedence",
+        trait,
+        method,
+        this.next().read_name_list()
+      );
+    } else if (this.token === this.tok.T_AS) {
+      // handle trait alias
+      let flags = null;
+      let alias = null;
+      if (this.next().is("T_MEMBER_FLAGS")) {
+        flags = this.read_member_flags();
+      }
+
+      if (
+        this.token === this.tok.T_STRING ||
+        (this.php7 && this.is("IDENTIFIER"))
+      ) {
+        alias = this.node("identifier");
+        const name = this.text();
+        this.next();
+        alias = alias(name);
+      } else if (flags === false) {
+        // no visibility flags and no name => too bad
+        this.expect(this.tok.T_STRING);
+      }
+
+      return node("traitalias", trait, method, alias, flags);
+    }
+
+    // handle errors
+    this.expect([this.tok.T_AS, this.tok.T_INSTEADOF]);
+    return node("traitalias", trait, method, null, null);
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_comment.js.html b/docs/parser_comment.js.html new file mode 100644 index 000000000..84586d934 --- /dev/null +++ b/docs/parser_comment.js.html @@ -0,0 +1,194 @@ + + + + + + + + + + + parser/comment.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/comment.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   *  Comments with // or # or / * ... * /
+   */
+  read_comment: function() {
+    const text = this.text();
+    let result = this.ast.prepare(
+      text.substring(0, 2) === "/*" ? "commentblock" : "commentline",
+      null,
+      this
+    );
+    const offset = this.lexer.yylloc.first_offset;
+    // handle location on comment
+    const prev = this.prev;
+    this.prev = [
+      this.lexer.yylloc.last_line,
+      this.lexer.yylloc.last_column,
+      this.lexer.offset
+    ];
+    this.lex();
+    result = result(text);
+    result.offset = offset;
+    this.prev = prev;
+    return result;
+  },
+  /**
+   * Comments with / ** ... * /
+   */
+  read_doc_comment: function() {
+    let result = this.ast.prepare("commentblock", null, this);
+    const offset = this.lexer.yylloc.first_offset;
+    const text = this.text();
+    const prev = this.prev;
+    this.prev = [
+      this.lexer.yylloc.last_line,
+      this.lexer.yylloc.last_column,
+      this.lexer.offset
+    ];
+    this.lex();
+    result = result(text);
+    result.offset = offset;
+    this.prev = prev;
+    return result;
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_expr.js.html b/docs/parser_expr.js.html new file mode 100644 index 000000000..fac731b07 --- /dev/null +++ b/docs/parser_expr.js.html @@ -0,0 +1,679 @@ + + + + + + + + + + + parser/expr.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/expr.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  read_expr: function(expr) {
+    const result = this.node();
+    if (!expr) {
+      expr = this.read_expr_item();
+    }
+    // binary operations
+    if (this.token === "|")
+      return result("bin", "|", expr, this.next().read_expr());
+    if (this.token === "&")
+      return result("bin", "&", expr, this.next().read_expr());
+    if (this.token === "^")
+      return result("bin", "^", expr, this.next().read_expr());
+    if (this.token === ".")
+      return result("bin", ".", expr, this.next().read_expr());
+    if (this.token === "+")
+      return result("bin", "+", expr, this.next().read_expr());
+    if (this.token === "-")
+      return result("bin", "-", expr, this.next().read_expr());
+    if (this.token === "*")
+      return result("bin", "*", expr, this.next().read_expr());
+    if (this.token === "/")
+      return result("bin", "/", expr, this.next().read_expr());
+    if (this.token === "%")
+      return result("bin", "%", expr, this.next().read_expr());
+    if (this.token === this.tok.T_POW)
+      return result("bin", "**", expr, this.next().read_expr());
+    if (this.token === this.tok.T_SL)
+      return result("bin", "<<", expr, this.next().read_expr());
+    if (this.token === this.tok.T_SR)
+      return result("bin", ">>", expr, this.next().read_expr());
+    // more binary operations (formerly bool)
+    if (this.token === this.tok.T_BOOLEAN_OR)
+      return result("bin", "||", expr, this.next().read_expr());
+    if (this.token === this.tok.T_LOGICAL_OR)
+      return result("bin", "or", expr, this.next().read_expr());
+    if (this.token === this.tok.T_BOOLEAN_AND)
+      return result("bin", "&&", expr, this.next().read_expr());
+    if (this.token === this.tok.T_LOGICAL_AND)
+      return result("bin", "and", expr, this.next().read_expr());
+    if (this.token === this.tok.T_LOGICAL_XOR)
+      return result("bin", "xor", expr, this.next().read_expr());
+    if (this.token === this.tok.T_IS_IDENTICAL)
+      return result("bin", "===", expr, this.next().read_expr());
+    if (this.token === this.tok.T_IS_NOT_IDENTICAL)
+      return result("bin", "!==", expr, this.next().read_expr());
+    if (this.token === this.tok.T_IS_EQUAL)
+      return result("bin", "==", expr, this.next().read_expr());
+    if (this.token === this.tok.T_IS_NOT_EQUAL)
+      return result("bin", "!=", expr, this.next().read_expr());
+    if (this.token === "<")
+      return result("bin", "<", expr, this.next().read_expr());
+    if (this.token === ">")
+      return result("bin", ">", expr, this.next().read_expr());
+    if (this.token === this.tok.T_IS_SMALLER_OR_EQUAL)
+      return result("bin", "<=", expr, this.next().read_expr());
+    if (this.token === this.tok.T_IS_GREATER_OR_EQUAL)
+      return result("bin", ">=", expr, this.next().read_expr());
+    if (this.token === this.tok.T_SPACESHIP)
+      return result("bin", "<=>", expr, this.next().read_expr());
+    if (this.token === this.tok.T_INSTANCEOF) {
+      expr = result(
+        "bin",
+        "instanceof",
+        expr,
+        this.next().read_class_name_reference()
+      );
+      if (
+        this.token !== ";" &&
+        this.token !== this.tok.T_INLINE_HTML &&
+        this.token !== this.EOF
+      ) {
+        expr = this.read_expr(expr);
+      }
+    }
+
+    // extra operations :
+    // $username = $_GET['user'] ?? 'nobody';
+    if (this.token === this.tok.T_COALESCE)
+      return result("bin", "??", expr, this.next().read_expr());
+
+    // extra operations :
+    // $username = $_GET['user'] ? true : false;
+    if (this.token === "?") {
+      let trueArg = null;
+      if (this.next().token !== ":") {
+        trueArg = this.read_expr();
+      }
+      this.expect(":") && this.next();
+      return result("retif", expr, trueArg, this.read_expr());
+    } else {
+      // see #193
+      result.destroy(expr);
+    }
+
+    return expr;
+  },
+
+  /**
+   * Reads a cast expression
+   */
+  read_expr_cast: function(type) {
+    return this.node("cast")(type, this.text(), this.next().read_expr());
+  },
+
+  /**
+   * ```ebnf
+   * Reads an expression
+   *  expr ::= @todo
+   * ```
+   */
+  read_expr_item: function() {
+    let result, expr;
+    if (this.token === "@") return this.node("silent")(this.next().read_expr());
+    if (this.token === "+")
+      return this.node("unary")("+", this.next().read_expr());
+    if (this.token === "-")
+      return this.node("unary")("-", this.next().read_expr());
+    if (this.token === "!")
+      return this.node("unary")("!", this.next().read_expr());
+    if (this.token === "~")
+      return this.node("unary")("~", this.next().read_expr());
+
+    if (this.token === "(") {
+      expr = this.next().read_expr();
+      expr.parenthesizedExpression = true;
+      this.expect(")") && this.next();
+      return this.handleDereferencable(expr);
+    }
+
+    if (this.token === "`") {
+      // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1048
+      return this.read_encapsed_string("`");
+    }
+
+    if (this.token === this.tok.T_LIST) {
+      let assign = null;
+      const isInner = this.innerList;
+      result = this.node("list");
+      if (!isInner) {
+        assign = this.node("assign");
+      }
+      if (this.next().expect("(")) {
+        this.next();
+      }
+
+      if (!this.innerList) this.innerList = true;
+
+      // reads inner items
+      const assignList = this.read_array_pair_list(false);
+      if (this.expect(")")) {
+        this.next();
+      }
+
+      // check if contains at least one assignment statement
+      let hasItem = false;
+      for (let i = 0; i < assignList.length; i++) {
+        if (assignList[i] !== null && assignList[i].kind !== "noop") {
+          hasItem = true;
+          break;
+        }
+      }
+      if (!hasItem) {
+        this.raiseError(
+          "Fatal Error :  Cannot use empty list on line " +
+            this.lexer.yylloc.first_line
+        );
+      }
+
+      // handles the node resolution
+      if (!isInner) {
+        this.innerList = false;
+        if (this.expect("=")) {
+          return assign(
+            result(assignList, false),
+            this.next().read_expr(),
+            "="
+          );
+        } else {
+          // error fallback : list($a, $b);
+          return result(assignList, false);
+        }
+      } else {
+        return result(assignList, false);
+      }
+    }
+
+    if (this.token === this.tok.T_CLONE)
+      return this.node("clone")(this.next().read_expr());
+
+    switch (this.token) {
+      case this.tok.T_INC:
+        return this.node("pre")(
+          "+",
+          this.next().read_variable(false, false, false)
+        );
+
+      case this.tok.T_DEC:
+        return this.node("pre")(
+          "-",
+          this.next().read_variable(false, false, false)
+        );
+
+      case this.tok.T_NEW:
+        return this.read_new_expr();
+
+      case this.tok.T_ISSET: {
+        result = this.node("isset");
+        if (this.next().expect("(")) {
+          this.next();
+        }
+        const variables = this.read_list(this.read_expr, ",");
+        if (this.expect(")")) {
+          this.next();
+        }
+        return result(variables);
+      }
+      case this.tok.T_EMPTY: {
+        result = this.node("empty");
+        if (this.next().expect("(")) {
+          this.next();
+        }
+        const expression = this.read_expr();
+        if (this.expect(")")) {
+          this.next();
+        }
+        return result(expression);
+      }
+      case this.tok.T_INCLUDE:
+        return this.node("include")(false, false, this.next().read_expr());
+
+      case this.tok.T_INCLUDE_ONCE:
+        return this.node("include")(true, false, this.next().read_expr());
+
+      case this.tok.T_REQUIRE:
+        return this.node("include")(false, true, this.next().read_expr());
+
+      case this.tok.T_REQUIRE_ONCE:
+        return this.node("include")(true, true, this.next().read_expr());
+
+      case this.tok.T_EVAL:
+        result = this.node("eval");
+        if (this.next().expect("(")) {
+          this.next();
+        }
+        expr = this.read_expr();
+        if (this.expect(")")) {
+          this.next();
+        }
+        return result(expr);
+
+      case this.tok.T_INT_CAST:
+        return this.read_expr_cast("int");
+
+      case this.tok.T_DOUBLE_CAST:
+        return this.read_expr_cast("float");
+
+      case this.tok.T_STRING_CAST:
+        return this.read_expr_cast(
+          this.text().indexOf("binary") !== -1 ? "binary" : "string"
+        );
+
+      case this.tok.T_ARRAY_CAST:
+        return this.read_expr_cast("array");
+
+      case this.tok.T_OBJECT_CAST:
+        return this.read_expr_cast("object");
+
+      case this.tok.T_BOOL_CAST:
+        return this.read_expr_cast("bool");
+
+      case this.tok.T_UNSET_CAST:
+        return this.read_expr_cast("unset");
+
+      case this.tok.T_EXIT: {
+        const useDie = this.lexer.yytext.toLowerCase() === "die";
+        result = this.node("exit");
+        let status = null;
+        if (this.next().token === "(") {
+          if (this.next().token !== ")") {
+            status = this.read_expr();
+            if (this.expect(")")) {
+              this.next();
+            }
+          } else {
+            this.next();
+          }
+        }
+        return result(status, useDie);
+      }
+
+      case this.tok.T_PRINT:
+        return this.node("print")(this.next().read_expr());
+
+      // T_YIELD (expr (T_DOUBLE_ARROW expr)?)?
+      case this.tok.T_YIELD: {
+        let value = null;
+        let key = null;
+        result = this.node("yield");
+        if (this.next().is("EXPR")) {
+          // reads the yield return value
+          value = this.read_expr();
+          if (this.token === this.tok.T_DOUBLE_ARROW) {
+            // reads the yield returned key
+            key = value;
+            value = this.next().read_expr();
+          }
+        }
+        return result(value, key);
+      }
+
+      // T_YIELD_FROM expr
+      case this.tok.T_YIELD_FROM:
+        result = this.node("yieldfrom");
+        expr = this.next().read_expr();
+        return result(expr);
+
+      case this.tok.T_FUNCTION:
+        return this.read_function(true);
+
+      case this.tok.T_STATIC: {
+        const backup = [this.token, this.lexer.getState()];
+        if (this.next().token === this.tok.T_FUNCTION) {
+          // handles static function
+          return this.read_function(true, [0, 1, 0]);
+        } else {
+          // rollback
+          this.lexer.tokens.push(backup);
+          this.next();
+        }
+      }
+    }
+
+    // SCALAR | VARIABLE
+    if (this.is("VARIABLE")) {
+      result = this.node();
+      expr = this.read_variable(false, false, false);
+
+      // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L877
+      // should accept only a variable
+      const isConst =
+        expr.kind === "identifier" ||
+        (expr.kind === "staticlookup" && expr.offset.kind === "identifier");
+
+      // VARIABLES SPECIFIC OPERATIONS
+      switch (this.token) {
+        case "=": {
+          if (isConst) this.error("VARIABLE");
+          let right;
+          if (this.next().token == "&") {
+            if (this.next().token === this.tok.T_NEW) {
+              if (this.php7) {
+                this.error();
+              }
+              right = this.read_new_expr();
+            } else {
+              right = this.read_variable(false, false, true);
+            }
+          } else {
+            right = this.read_expr();
+          }
+          return result("assign", expr, right, "=");
+        }
+
+        // operations :
+        case this.tok.T_PLUS_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), "+=");
+
+        case this.tok.T_MINUS_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), "-=");
+
+        case this.tok.T_MUL_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), "*=");
+
+        case this.tok.T_POW_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), "**=");
+
+        case this.tok.T_DIV_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), "/=");
+
+        case this.tok.T_CONCAT_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), ".=");
+
+        case this.tok.T_MOD_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), "%=");
+
+        case this.tok.T_AND_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), "&=");
+
+        case this.tok.T_OR_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), "|=");
+
+        case this.tok.T_XOR_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), "^=");
+
+        case this.tok.T_SL_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), "<<=");
+
+        case this.tok.T_SR_EQUAL:
+          if (isConst) this.error("VARIABLE");
+          return result("assign", expr, this.next().read_expr(), ">>=");
+
+        case this.tok.T_INC:
+          if (isConst) this.error("VARIABLE");
+          this.next();
+          return result("post", "+", expr);
+        case this.tok.T_DEC:
+          if (isConst) this.error("VARIABLE");
+          this.next();
+          return result("post", "-", expr);
+        default:
+          // see #193
+          result.destroy(expr);
+      }
+    } else if (this.is("SCALAR")) {
+      result = this.node();
+      expr = this.read_scalar();
+      if (expr.kind === "array" && expr.shortForm && this.token === "=") {
+        // list assign
+        const list = this.node("list")(expr.items, true);
+        if (expr.loc) list.loc = expr.loc;
+        const right = this.next().read_expr();
+        return result("assign", list, right, "=");
+      } else {
+        // see #189 - swap docs on nodes
+        result.destroy(expr);
+      }
+      // classic array
+      return this.handleDereferencable(expr);
+    } else {
+      this.error("EXPR");
+      this.next();
+    }
+
+    // returns variable | scalar
+    return expr;
+  },
+  /**
+   * ```ebnf
+   *    new_expr ::= T_NEW (namespace_name function_argument_list) | (T_CLASS ... class declaration)
+   * ```
+   * https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L850
+   */
+  read_new_expr: function() {
+    const result = this.node("new");
+    this.expect(this.tok.T_NEW) && this.next();
+    let args = [];
+    if (this.token === this.tok.T_CLASS) {
+      const what = this.node("class");
+      // Annonymous class declaration
+      let propExtends = null,
+        propImplements = null,
+        body = null;
+      if (this.next().token === "(") {
+        args = this.read_function_argument_list();
+      }
+      if (this.token == this.tok.T_EXTENDS) {
+        propExtends = this.next().read_namespace_name();
+      }
+      if (this.token == this.tok.T_IMPLEMENTS) {
+        propImplements = this.next().read_name_list();
+      }
+      if (this.expect("{")) {
+        body = this.next().read_class_body();
+      }
+      return result(
+        what(null, propExtends, propImplements, body, [0, 0, 0]),
+        args
+      );
+    }
+    // Already existing class
+    const name = this.read_new_class_name();
+    if (this.token === "(") {
+      args = this.read_function_argument_list();
+    }
+    return result(name, args);
+  },
+  /**
+   * Reads a class name
+   * ```ebnf
+   * read_new_class_name ::= namespace_name | variable
+   * ```
+   */
+  read_new_class_name: function() {
+    if (
+      this.token === this.tok.T_NS_SEPARATOR ||
+      this.token === this.tok.T_STRING ||
+      this.token === this.tok.T_NAMESPACE
+    ) {
+      let result = this.read_namespace_name(true);
+      if (this.token === this.tok.T_DOUBLE_COLON) {
+        result = this.read_static_getter(result);
+      }
+      return result;
+    } else if (this.is("VARIABLE")) {
+      return this.read_variable(true, false, false);
+    } else {
+      this.expect([this.tok.T_STRING, "VARIABLE"]);
+    }
+  },
+  handleDereferencable: function(expr) {
+    while (this.token !== this.EOF) {
+      if (
+        this.token === this.tok.T_OBJECT_OPERATOR ||
+        this.token === this.tok.T_DOUBLE_COLON
+      ) {
+        expr = this.recursive_variable_chain_scan(expr, false, false, true);
+      } else if (this.token === this.tok.T_CURLY_OPEN || this.token === "[") {
+        expr = this.read_dereferencable(expr);
+      } else if (this.token === "(") {
+        // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118
+        expr = this.node("call")(expr, this.read_function_argument_list());
+      } else {
+        return expr;
+      }
+    }
+    return expr;
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_function.js.html b/docs/parser_function.js.html new file mode 100644 index 000000000..6535d873a --- /dev/null +++ b/docs/parser_function.js.html @@ -0,0 +1,433 @@ + + + + + + + + + + + parser/function.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/function.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * checks if current token is a reference keyword
+   */
+  is_reference: function() {
+    if (this.token == "&") {
+      this.next();
+      return true;
+    }
+    return false;
+  },
+  /**
+   * checks if current token is a variadic keyword
+   */
+  is_variadic: function() {
+    if (this.token === this.tok.T_ELLIPSIS) {
+      this.next();
+      return true;
+    }
+    return false;
+  },
+  /**
+   * reading a function
+   * ```ebnf
+   * function ::= function_declaration code_block
+   * ```
+   */
+  read_function: function(closure, flag) {
+    const result = this.read_function_declaration(
+      closure ? 1 : flag ? 2 : 0,
+      flag && flag[1] === 1
+    );
+    if (flag && flag[2] == 1) {
+      // abstract function :
+      result.parseFlags(flag);
+      if (this.expect(";")) {
+        this.next();
+      }
+    } else {
+      if (this.expect("{")) {
+        result.body = this.read_code_block(false);
+        if (result.loc && result.body.loc) {
+          result.loc.end = result.body.loc.end;
+        }
+      }
+      if (!closure && flag) {
+        result.parseFlags(flag);
+      }
+    }
+    return result;
+  },
+  /**
+   * reads a function declaration (without his body)
+   * ```ebnf
+   * function_declaration ::= T_FUNCTION '&'?  T_STRING '(' parameter_list ')'
+   * ```
+   */
+  read_function_declaration: function(type, isStatic) {
+    let nodeName = "function";
+    if (type === 1) {
+      nodeName = "closure";
+    } else if (type === 2) {
+      nodeName = "method";
+    }
+    const result = this.node(nodeName);
+
+    if (this.expect(this.tok.T_FUNCTION)) {
+      this.next();
+    }
+    const isRef = this.is_reference();
+    let name = false,
+      use = [],
+      returnType = null,
+      nullable = false;
+    if (type !== 1) {
+      const nameNode = this.node("identifier");
+      if (type === 2) {
+        if (this.php7) {
+          if (this.token === this.tok.T_STRING || this.is("IDENTIFIER")) {
+            name = this.text();
+            this.next();
+          } else if (!this.php74) {
+            this.error("IDENTIFIER");
+          }
+        } else if (this.token === this.tok.T_STRING) {
+          name = this.text();
+          this.next();
+        } else {
+          this.error("IDENTIFIER");
+        }
+      } else {
+        if (this.php7) {
+          if (this.token === this.tok.T_STRING) {
+            name = this.text();
+            this.next();
+          } else if (this.php74) {
+            if (!this.expect("(")) {
+              this.next();
+            }
+          } else {
+            this.error(this.tok.T_STRING);
+            this.next();
+          }
+        } else {
+          if (this.expect(this.tok.T_STRING)) {
+            name = this.text();
+          }
+          this.next();
+        }
+      }
+      name = nameNode(name);
+    }
+    if (this.expect("(")) this.next();
+    const params = this.read_parameter_list();
+    if (this.expect(")")) this.next();
+    if (type === 1 && this.token === this.tok.T_USE) {
+      if (this.next().expect("(")) this.next();
+      use = this.read_list(this.read_lexical_var, ",");
+      if (this.expect(")")) this.next();
+    }
+    if (this.token === ":") {
+      if (this.next().token === "?") {
+        nullable = true;
+        this.next();
+      }
+      returnType = this.read_type();
+    }
+    if (type === 1) {
+      // closure
+      return result(params, isRef, use, returnType, nullable, isStatic);
+    }
+    return result(name, params, isRef, returnType, nullable);
+  },
+  /**
+   * ```ebnf
+   * lexical_var ::= '&'? T_VARIABLE
+   * ```
+   */
+  read_lexical_var: function() {
+    const result = this.node("variable");
+    let isRef = false;
+    if (this.token === "&") {
+      isRef = true;
+      this.next();
+    }
+    this.expect(this.tok.T_VARIABLE);
+    const name = this.text().substring(1);
+    this.next();
+    return result(name, isRef, false);
+  },
+  /**
+   * reads a list of parameters
+   * ```ebnf
+   *  parameter_list ::= (parameter ',')* parameter?
+   * ```
+   */
+  read_parameter_list: function() {
+    const result = [];
+    if (this.token != ")") {
+      while (this.token != this.EOF) {
+        result.push(this.read_parameter());
+        if (this.token == ",") {
+          this.next();
+        } else if (this.token == ")") {
+          break;
+        } else {
+          this.error([",", ")"]);
+          break;
+        }
+      }
+    }
+    return result;
+  },
+  /**
+   * ```ebnf
+   *  parameter ::= type? '&'? T_ELLIPSIS? T_VARIABLE ('=' expr)?
+   * ```
+   * @see https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L640
+   */
+  read_parameter: function() {
+    const node = this.node("parameter");
+    let parameterName = null;
+    let value = null;
+    let type = null;
+    let nullable = false;
+    if (this.token === "?") {
+      this.next();
+      nullable = true;
+    }
+    type = this.read_type();
+    if (nullable && !type) {
+      this.raiseError(
+        "Expecting a type definition combined with nullable operator"
+      );
+    }
+    const isRef = this.is_reference();
+    const isVariadic = this.is_variadic();
+    if (this.expect(this.tok.T_VARIABLE)) {
+      parameterName = this.node("identifier");
+      const name = this.text().substring(1);
+      this.next();
+      parameterName = parameterName(name);
+    }
+    if (this.token == "=") {
+      value = this.next().read_expr();
+    }
+    return node(parameterName, type, value, isRef, isVariadic, nullable);
+  },
+  /**
+   * Reads a list of arguments
+   * ```ebnf
+   *  function_argument_list ::= '(' (argument_list (',' argument_list)*)? ')'
+   * ```
+   */
+  read_function_argument_list: function() {
+    const result = [];
+    let wasVariadic = false;
+    this.expect("(") && this.next();
+    if (this.token !== ")") {
+      while (this.token != this.EOF) {
+        const argument = this.read_argument_list();
+        if (argument) {
+          result.push(argument);
+          if (argument.kind === "variadic") {
+            wasVariadic = true;
+          } else if (wasVariadic) {
+            this.raiseError("Unexpected argument after a variadic argument");
+          }
+        }
+        if (this.token === ",") {
+          this.next();
+        } else break;
+      }
+    }
+    this.expect(")") && this.next();
+    return result;
+  },
+  /**
+   * ```ebnf
+   *    argument_list ::= T_ELLIPSIS? expr
+   * ```
+   */
+  read_argument_list: function() {
+    if (this.token === this.tok.T_ELLIPSIS) {
+      return this.node("variadic")(this.next().read_expr());
+    }
+    return this.read_expr();
+  },
+  /**
+   * read type hinting
+   * ```ebnf
+   *  type ::= T_ARRAY | T_CALLABLE | namespace_name
+   * ```
+   */
+  read_type: function() {
+    const result = this.node();
+    if (this.token === this.tok.T_ARRAY || this.token === this.tok.T_CALLABLE) {
+      const type = this.text();
+      this.next();
+      return result("typereference", type.toLowerCase(), type);
+    } else if (this.token === this.tok.T_STRING) {
+      const type = this.text();
+      const backup = [this.token, this.lexer.getState()];
+      this.next();
+      if (
+        this.token !== this.tok.T_NS_SEPARATOR &&
+        this.ast.typereference.types.indexOf(type.toLowerCase()) > -1
+      ) {
+        return result("typereference", type.toLowerCase(), type);
+      } else {
+        // rollback a classic namespace
+        this.lexer.tokens.push(backup);
+        this.next();
+        return this.read_namespace_name();
+      }
+    } else if (
+      this.token === this.tok.T_NAMESPACE ||
+      this.token === this.tok.T_NS_SEPARATOR
+    ) {
+      return this.read_namespace_name();
+    }
+    return null;
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_if.js.html b/docs/parser_if.js.html new file mode 100644 index 000000000..c7cbd03bc --- /dev/null +++ b/docs/parser_if.js.html @@ -0,0 +1,240 @@ + + + + + + + + + + + parser/if.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/if.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * Reads an IF statement
+   *
+   * ```ebnf
+   *  if ::= T_IF '(' expr ')' ':' ...
+   * ```
+   */
+  read_if: function() {
+    const result = this.node("if");
+    let body = null;
+    let alternate = null;
+    let shortForm = false;
+    let test = null;
+    test = this.next().read_if_expr();
+
+    if (this.token === ":") {
+      shortForm = true;
+      this.next();
+      body = this.node("block");
+      const items = [];
+      while (this.token !== this.EOF && this.token !== this.tok.T_ENDIF) {
+        if (this.token === this.tok.T_ELSEIF) {
+          alternate = this.read_elseif_short();
+          break;
+        } else if (this.token === this.tok.T_ELSE) {
+          alternate = this.read_else_short();
+          break;
+        }
+        items.push(this.read_inner_statement());
+      }
+      body = body(null, items);
+      this.expect(this.tok.T_ENDIF) && this.next();
+      this.expectEndOfStatement();
+    } else {
+      body = this.read_statement();
+      if (this.token === this.tok.T_ELSEIF) {
+        alternate = this.read_if();
+      } else if (this.token === this.tok.T_ELSE) {
+        alternate = this.next().read_statement();
+      }
+    }
+    return result(test, body, alternate, shortForm);
+  },
+  /**
+   * reads an if expression : '(' expr ')'
+   */
+  read_if_expr: function() {
+    this.expect("(") && this.next();
+    const result = this.read_expr();
+    this.expect(")") && this.next();
+    return result;
+  },
+  /**
+   * reads an elseif (expr): statements
+   */
+  read_elseif_short: function() {
+    const result = this.node("if");
+    let alternate = null;
+    let test = null;
+    let body = null;
+    const items = [];
+    test = this.next().read_if_expr();
+    if (this.expect(":")) this.next();
+    body = this.node("block");
+    while (this.token != this.EOF && this.token !== this.tok.T_ENDIF) {
+      if (this.token === this.tok.T_ELSEIF) {
+        alternate = this.read_elseif_short();
+        break;
+      } else if (this.token === this.tok.T_ELSE) {
+        alternate = this.read_else_short();
+        break;
+      }
+      items.push(this.read_inner_statement());
+    }
+    body = body(null, items);
+    return result(test, body, alternate, true);
+  },
+  /**
+   *
+   */
+  read_else_short: function() {
+    const body = this.node("block");
+    if (this.next().expect(":")) this.next();
+    const items = [];
+    while (this.token != this.EOF && this.token !== this.tok.T_ENDIF) {
+      items.push(this.read_inner_statement());
+    }
+    return body(null, items);
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_loops.js.html b/docs/parser_loops.js.html new file mode 100644 index 000000000..e38b8fd6e --- /dev/null +++ b/docs/parser_loops.js.html @@ -0,0 +1,310 @@ + + + + + + + + + + + parser/loops.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/loops.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * Reads a while statement
+   * ```ebnf
+   * while ::= T_WHILE (statement | ':' inner_statement_list T_ENDWHILE ';')
+   * ```
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L587
+   * @return {While}
+   */
+  read_while: function() {
+    const result = this.node("while");
+    this.expect(this.tok.T_WHILE) && this.next();
+    let test = null;
+    let body = null;
+    let shortForm = false;
+    if (this.expect("(")) this.next();
+    test = this.read_expr();
+    if (this.expect(")")) this.next();
+    if (this.token === ":") {
+      shortForm = true;
+      body = this.read_short_form(this.tok.T_ENDWHILE);
+    } else {
+      body = this.read_statement();
+    }
+    return result(test, body, shortForm);
+  },
+  /**
+   * Reads a do / while loop
+   * ```ebnf
+   * do ::= T_DO statement T_WHILE '(' expr ')' ';'
+   * ```
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L423
+   * @return {Do}
+   */
+  read_do: function() {
+    const result = this.node("do");
+    this.expect(this.tok.T_DO) && this.next();
+    let test = null;
+    let body = null;
+    body = this.read_statement();
+    if (this.expect(this.tok.T_WHILE)) {
+      if (this.next().expect("(")) this.next();
+      test = this.read_expr();
+      if (this.expect(")")) this.next();
+      if (this.expect(";")) this.next();
+    }
+    return result(test, body);
+  },
+  /**
+   * Read a for incremental loop
+   * ```ebnf
+   * for ::= T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement
+   * for_statement ::= statement | ':' inner_statement_list T_ENDFOR ';'
+   * for_exprs ::= expr? (',' expr)*
+   * ```
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L425
+   * @return {For}
+   */
+  read_for: function() {
+    const result = this.node("for");
+    this.expect(this.tok.T_FOR) && this.next();
+    let init = [];
+    let test = [];
+    let increment = [];
+    let body = null;
+    let shortForm = false;
+    if (this.expect("(")) this.next();
+    if (this.token !== ";") {
+      init = this.read_list(this.read_expr, ",");
+      if (this.expect(";")) this.next();
+    } else {
+      this.next();
+    }
+    if (this.token !== ";") {
+      test = this.read_list(this.read_expr, ",");
+      if (this.expect(";")) this.next();
+    } else {
+      this.next();
+    }
+    if (this.token !== ")") {
+      increment = this.read_list(this.read_expr, ",");
+      if (this.expect(")")) this.next();
+    } else {
+      this.next();
+    }
+    if (this.token === ":") {
+      shortForm = true;
+      body = this.read_short_form(this.tok.T_ENDFOR);
+    } else {
+      body = this.read_statement();
+    }
+    return result(init, test, increment, body, shortForm);
+  },
+  /**
+   * Reads a foreach loop
+   * ```ebnf
+   * foreach ::= '(' expr T_AS foreach_variable (T_DOUBLE_ARROW foreach_variable)? ')' statement
+   * ```
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L438
+   * @return {Foreach}
+   */
+  read_foreach: function() {
+    const result = this.node("foreach");
+    this.expect(this.tok.T_FOREACH) && this.next();
+    let source = null;
+    let key = null;
+    let value = null;
+    let body = null;
+    let shortForm = false;
+    if (this.expect("(")) this.next();
+    source = this.read_expr();
+    if (this.expect(this.tok.T_AS)) {
+      this.next();
+      value = this.read_foreach_variable();
+      if (this.token === this.tok.T_DOUBLE_ARROW) {
+        key = value;
+        value = this.next().read_foreach_variable();
+      }
+    }
+
+    // grammatically correct but not supported by PHP
+    if (key && key.kind === "list") {
+      this.raiseError("Fatal Error : Cannot use list as key element");
+    }
+
+    if (this.expect(")")) this.next();
+
+    if (this.token === ":") {
+      shortForm = true;
+      body = this.read_short_form(this.tok.T_ENDFOREACH);
+    } else {
+      body = this.read_statement();
+    }
+    return result(source, key, value, body, shortForm);
+  },
+  /**
+   * Reads a foreach variable statement
+   * ```ebnf
+   * foreach_variable =
+   *    variable |
+   *    '&' variable |
+   *    T_LIST '(' assignment_list ')' |
+   *    '[' assignment_list ']'
+   * ```
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L544
+   * @return {Expression}
+   */
+  read_foreach_variable: function() {
+    if (this.token === this.tok.T_LIST || this.token === "[") {
+      const isShort = this.token === "[";
+      const result = this.node("list");
+      this.next();
+      if (!isShort && this.expect("(")) this.next();
+      const assignList = this.read_array_pair_list(isShort);
+      if (this.expect(isShort ? "]" : ")")) this.next();
+      return result(assignList, isShort);
+    } else {
+      return this.read_variable(false, false, false);
+    }
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_main.js.html b/docs/parser_main.js.html new file mode 100644 index 000000000..f1cd6a2aa --- /dev/null +++ b/docs/parser_main.js.html @@ -0,0 +1,163 @@ + + + + + + + + + + + parser/main.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/main.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * ```ebnf
+   * start ::= (namespace | top_statement)*
+   * ```
+   */
+  read_start: function() {
+    if (this.token == this.tok.T_NAMESPACE) {
+      return this.read_namespace();
+    } else {
+      return this.read_top_statement();
+    }
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_namespace.js.html b/docs/parser_namespace.js.html new file mode 100644 index 000000000..0d0c0081a --- /dev/null +++ b/docs/parser_namespace.js.html @@ -0,0 +1,353 @@ + + + + + + + + + + + parser/namespace.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/namespace.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * Reads a namespace declaration block
+   * ```ebnf
+   * namespace ::= T_NAMESPACE namespace_name? '{'
+   *    top_statements
+   * '}'
+   * | T_NAMESPACE namespace_name ';' top_statements
+   * ```
+   * @see http://php.net/manual/en/language.namespaces.php
+   * @return {Namespace}
+   */
+  read_namespace: function() {
+    const result = this.node("namespace");
+    let body;
+    this.expect(this.tok.T_NAMESPACE) && this.next();
+    if (this.token == "{") {
+      this.currentNamespace = [""];
+      body = this.next().read_top_statements();
+      this.expect("}") && this.next();
+      return result([""], body, true);
+    } else {
+      const name = this.read_namespace_name();
+      if (this.token == ";") {
+        this.currentNamespace = name;
+        body = this.next().read_top_statements();
+        this.expect(this.EOF);
+        return result(name.name, body, false);
+      } else if (this.token == "{") {
+        this.currentNamespace = name;
+        body = this.next().read_top_statements();
+        this.expect("}") && this.next();
+        return result(name.name, body, true);
+      } else if (this.token === "(") {
+        // resolve ambuiguity between namespace & function call
+        name.resolution = this.ast.reference.RELATIVE_NAME;
+        name.name = name.name.substring(1);
+        result.destroy();
+        return this.node("call")(name, this.read_function_argument_list());
+      } else {
+        this.error(["{", ";"]);
+        // graceful mode :
+        this.currentNamespace = name;
+        body = this.read_top_statements();
+        this.expect(this.EOF);
+        return result(name, body, false);
+      }
+    }
+  },
+  /**
+   * Reads a namespace name
+   * ```ebnf
+   *  namespace_name ::= T_NS_SEPARATOR? (T_STRING T_NS_SEPARATOR)* T_STRING
+   * ```
+   * @see http://php.net/manual/en/language.namespaces.rules.php
+   * @return {Reference}
+   */
+  read_namespace_name: function(resolveReference) {
+    const result = this.node();
+    let relative = false;
+    if (this.token === this.tok.T_NAMESPACE) {
+      this.next().expect(this.tok.T_NS_SEPARATOR) && this.next();
+      relative = true;
+    }
+    const names = this.read_list(
+      this.tok.T_STRING,
+      this.tok.T_NS_SEPARATOR,
+      true
+    );
+    if (
+      !relative &&
+      names.length === 1 &&
+      (resolveReference || this.token !== "(")
+    ) {
+      if (names[0].toLowerCase() === "parent") {
+        return result("parentreference", names[0]);
+      } else if (names[0].toLowerCase() === "self") {
+        return result("selfreference", names[0]);
+      }
+    }
+    return result("classreference", names, relative);
+  },
+  /**
+   * Reads a use statement
+   * ```ebnf
+   * use_statement ::= T_USE
+   *   use_type? use_declarations |
+   *   use_type use_statement '{' use_declarations '}' |
+   *   use_statement '{' use_declarations(=>typed) '}'
+   * ';'
+   * ```
+   * @see http://php.net/manual/en/language.namespaces.importing.php
+   * @return {UseGroup}
+   */
+  read_use_statement: function() {
+    let result = this.node("usegroup");
+    let items = [];
+    let name = null;
+    this.expect(this.tok.T_USE) && this.next();
+    const type = this.read_use_type();
+    items.push(this.read_use_declaration(false));
+    if (this.token === ",") {
+      items = items.concat(this.next().read_use_declarations(false));
+    } else if (this.token === "{") {
+      name = items[0].name;
+      items = this.next().read_use_declarations(type === null);
+      this.expect("}") && this.next();
+    }
+    result = result(name, type, items);
+    this.expect(";") && this.next();
+    return result;
+  },
+  /**
+   *
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1045
+   */
+  read_class_name_reference: function() {
+    // resolved as the same
+    return this.read_variable(true, false, false);
+  },
+  /**
+   * Reads a use declaration
+   * ```ebnf
+   * use_declaration ::= use_type? namespace_name use_alias
+   * ```
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L380
+   * @return {UseItem}
+   */
+  read_use_declaration: function(typed) {
+    const result = this.node("useitem");
+    let type = null;
+    if (typed) type = this.read_use_type();
+    const name = this.read_namespace_name();
+    const alias = this.read_use_alias();
+    return result(name.name, alias, type);
+  },
+  /**
+   * Reads a list of use declarations
+   * ```ebnf
+   * use_declarations ::= use_declaration (',' use_declaration)*
+   * ```
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L380
+   * @return {UseItem[]}
+   */
+  read_use_declarations: function(typed) {
+    const result = [this.read_use_declaration(typed)];
+    while (this.token === ",") {
+      this.next();
+      if (typed) {
+        if (
+          this.token !== this.tok.T_FUNCTION &&
+          this.token !== this.tok.T_CONST &&
+          this.token !== this.tok.T_STRING
+        ) {
+          break;
+        }
+      } else if (
+        this.token !== this.tok.T_STRING &&
+        this.token !== this.tok.T_NS_SEPARATOR
+      ) {
+        break;
+      }
+      result.push(this.read_use_declaration(typed));
+    }
+    return result;
+  },
+  /**
+   * Reads a use statement
+   * ```ebnf
+   * use_alias ::= (T_AS T_STRING)?
+   * ```
+   * @return {String|null}
+   */
+  read_use_alias: function() {
+    let result = null;
+    if (this.token === this.tok.T_AS) {
+      if (this.next().expect(this.tok.T_STRING)) {
+        const aliasName = this.node("identifier");
+        const name = this.text();
+        this.next();
+        result = aliasName(name);
+      }
+    }
+    return result;
+  },
+  /**
+   * Reads the namespace type declaration
+   * ```ebnf
+   * use_type ::= (T_FUNCTION | T_CONST)?
+   * ```
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L335
+   * @return {String|null} Possible values : function, const
+   */
+  read_use_type: function() {
+    if (this.token === this.tok.T_FUNCTION) {
+      this.next();
+      return this.ast.useitem.TYPE_FUNCTION;
+    } else if (this.token === this.tok.T_CONST) {
+      this.next();
+      return this.ast.useitem.TYPE_CONST;
+    }
+    return null;
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_scalar.js.html b/docs/parser_scalar.js.html new file mode 100644 index 000000000..cea8b5adb --- /dev/null +++ b/docs/parser_scalar.js.html @@ -0,0 +1,451 @@ + + + + + + + + + + + parser/scalar.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/scalar.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+const specialChar = {
+  "\\r": "\r",
+  "\\n": "\n",
+  "\\t": "\t",
+  "\\v": String.fromCharCode(11),
+  "\\e": String.fromCharCode(27),
+  "\\f": String.fromCharCode(12),
+  "\\\\": "\\",
+  "\\$": "$",
+  '\\"': '"',
+  "\\'": "'"
+};
+
+module.exports = {
+  /**
+   * Unescape special chars
+   */
+  resolve_special_chars: function(text, doubleQuote) {
+    if (!doubleQuote) {
+      // single quote fix
+      return text.replace(/\\['\\]/g, function(seq) {
+        return specialChar[seq];
+      });
+    }
+    return text.replace(/\\[rntvef"'\\$]/g, function(seq) {
+      return specialChar[seq];
+    });
+  },
+  /**
+   * ```ebnf
+   *  scalar ::= T_MAGIC_CONST
+   *       | T_LNUMBER | T_DNUMBER
+   *       | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE? T_END_HEREDOC
+   *       | '"' encaps_list '"'
+   *       | T_START_HEREDOC encaps_list T_END_HEREDOC
+   *       | namespace_name (T_DOUBLE_COLON T_STRING)?
+   * ```
+   */
+  read_scalar: function() {
+    if (this.is("T_MAGIC_CONST")) {
+      return this.get_magic_constant();
+    } else {
+      let value, node;
+      switch (this.token) {
+        // TEXTS
+        case this.tok.T_CONSTANT_ENCAPSED_STRING: {
+          value = this.node("string");
+          const text = this.text();
+          let offset = 0;
+          if (text[0] === "b" || text[0] === "B") {
+            offset = 1;
+          }
+          const isDoubleQuote = text[offset] === '"';
+          this.next();
+          value = value(
+            isDoubleQuote,
+            this.resolve_special_chars(
+              text.substring(offset + 1, text.length - 1),
+              isDoubleQuote
+            ),
+            offset === 1, // unicode flag
+            text
+          );
+          if (this.token === this.tok.T_DOUBLE_COLON) {
+            // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1151
+            return this.read_static_getter(value);
+          } else {
+            // dirrect string
+            return value;
+          }
+        }
+        case this.tok.T_START_HEREDOC:
+          if (this.lexer.curCondition === "ST_NOWDOC") {
+            const start = this.lexer.yylloc.first_offset;
+            node = this.node("nowdoc");
+            value = this.next().text();
+            // strip the last line return char
+            const lastCh = value[value.length - 1];
+            if (lastCh === "\n") {
+              if (value[value.length - 2] === "\r") {
+                // windows style
+                value = value.substring(0, value.length - 2);
+              } else {
+                // linux style
+                value = value.substring(0, value.length - 1);
+              }
+            } else if (lastCh === "\r") {
+              // mac style
+              value = value.substring(0, value.length - 1);
+            }
+            this.expect(this.tok.T_ENCAPSED_AND_WHITESPACE) && this.next();
+            const raw = this.lexer._input.substring(
+              start,
+              this.lexer.yylloc.last_offset
+            );
+            this.expect(this.tok.T_END_HEREDOC) && this.next();
+            node = node(
+              value,
+              raw,
+              this.lexer.heredoc_label,
+              raw[3] === '"' || raw[3] === "'"
+            );
+            return node;
+          } else {
+            return this.read_encapsed_string(this.tok.T_END_HEREDOC);
+          }
+
+        case '"':
+          return this.read_encapsed_string('"');
+
+        case 'b"':
+        case 'B"': {
+          return this.read_encapsed_string('"', true);
+        }
+
+        // NUMERIC
+        case this.tok.T_LNUMBER: // long
+        case this.tok.T_DNUMBER: {
+          // double
+          const result = this.node("number");
+          value = this.text();
+          this.next();
+          return result(value, null);
+        }
+
+        // ARRAYS
+        case this.tok.T_ARRAY: // array parser
+          return this.read_array();
+        case "[": // short array format
+          return this.read_array();
+        default: {
+          const err = this.error("SCALAR");
+          // graceful mode : ignore token & return error node
+          this.next();
+          return err;
+        }
+      }
+    }
+  },
+  /**
+   * Handles the dereferencing
+   */
+  read_dereferencable: function(expr) {
+    let result, offset;
+    const node = this.node("offsetlookup");
+    if (this.token === "[") {
+      offset = this.next().read_expr();
+      if (this.expect("]")) this.next();
+      result = node(expr, offset);
+    } else if (this.token === this.tok.T_DOLLAR_OPEN_CURLY_BRACES) {
+      offset = this.read_encapsed_string_item(false);
+      result = node(expr, offset);
+    }
+    return result;
+  },
+  /**
+   * Reads and extracts an encapsed item
+   * ```ebnf
+   * encapsed_string_item ::= T_ENCAPSED_AND_WHITESPACE
+   *  | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
+   *  | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}'
+   *  | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
+   *  | T_CURLY_OPEN variable '}'
+   *  | variable
+   *  | variable '[' expr ']'
+   *  | variable T_OBJECT_OPERATOR T_STRING
+   * ```
+   * @return {String|Variable|Expr|Lookup}
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1219
+   */
+  read_encapsed_string_item: function(isDoubleQuote) {
+    const encapsedPart = this.node("encapsedpart");
+    let curly = false;
+    let result = this.node(),
+      offset,
+      node,
+      name;
+
+    // plain text
+    // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1222
+    if (this.token === this.tok.T_ENCAPSED_AND_WHITESPACE) {
+      const text = this.text();
+      this.next();
+      result = result(
+        "string",
+        false,
+        this.resolve_special_chars(text, isDoubleQuote),
+        false,
+        text
+      );
+    } else if (this.token === this.tok.T_DOLLAR_OPEN_CURLY_BRACES) {
+      // dynamic variable name
+      // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1239
+      name = null;
+      if (this.next().token === this.tok.T_STRING_VARNAME) {
+        name = this.node("variable");
+        const varName = this.text();
+        this.next();
+        // check if lookup an offset
+        // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1243
+        if (this.token === "[") {
+          name = name(varName, false, false);
+          node = this.node("offsetlookup");
+          offset = this.next().read_expr();
+          this.expect("]") && this.next();
+          name = node(name, offset);
+        } else {
+          name = varName;
+        }
+      } else {
+        name = this.read_expr();
+      }
+      this.expect("}") && this.next();
+      result = result("variable", name, false, true);
+    } else if (this.token === this.tok.T_CURLY_OPEN) {
+      // expression
+      // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1246
+      curly = true;
+      result.destroy();
+      result = this.next().read_variable(false, false, false);
+      this.expect("}") && this.next();
+    } else if (this.token === this.tok.T_VARIABLE) {
+      // plain variable
+      // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1231
+      result.destroy();
+      result = this.read_simple_variable(false);
+
+      // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1233
+      if (this.token === "[") {
+        node = this.node("offsetlookup");
+        offset = this.next().read_encaps_var_offset();
+        this.expect("]") && this.next();
+        result = node(result, offset);
+      }
+
+      // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1236
+      if (this.token === this.tok.T_OBJECT_OPERATOR) {
+        node = this.node("propertylookup");
+        this.next().expect(this.tok.T_STRING);
+        const what = this.node("identifier");
+        name = this.text();
+        this.next();
+        result = node(result, what(name));
+      }
+
+      // error / fallback
+    } else {
+      this.expect(this.tok.T_ENCAPSED_AND_WHITESPACE);
+      const value = this.text();
+      this.next();
+      // consider it as string
+      result.destroy();
+      result = result("string", false, value, false, value);
+    }
+
+    return encapsedPart(result, curly);
+  },
+  /**
+   * Reads an encapsed string
+   */
+  read_encapsed_string: function(expect, isBinary = false) {
+    let node = this.node("encapsed");
+    this.next();
+    const start = this.lexer.yylloc.prev_offset - (isBinary ? 1 : 0);
+    const value = [];
+    let type = null;
+
+    if (expect === "`") {
+      type = this.ast.encapsed.TYPE_SHELL;
+    } else if (expect === '"') {
+      type = this.ast.encapsed.TYPE_STRING;
+    } else {
+      type = this.ast.encapsed.TYPE_HEREDOC;
+    }
+
+    // reading encapsed parts
+    while (this.token !== expect && this.token !== this.EOF) {
+      value.push(this.read_encapsed_string_item(true));
+    }
+
+    this.expect(expect) && this.next();
+    node = node(
+      value,
+      this.lexer._input.substring(start - 1, this.lexer.yylloc.first_offset),
+      type
+    );
+
+    if (expect === this.tok.T_END_HEREDOC) {
+      node.label = this.lexer.heredoc_label;
+    }
+    return node;
+  },
+  /**
+   * Constant token
+   */
+  get_magic_constant: function() {
+    const result = this.node("magic");
+    const name = this.text();
+    this.next();
+    return result(name.toUpperCase(), name);
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_statement.js.html b/docs/parser_statement.js.html new file mode 100644 index 000000000..1d7254253 --- /dev/null +++ b/docs/parser_statement.js.html @@ -0,0 +1,547 @@ + + + + + + + + + + + parser/statement.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/statement.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * reading a list of top statements (helper for top_statement*)
+   * ```ebnf
+   *  top_statements ::= top_statement*
+   * ```
+   */
+  read_top_statements: function() {
+    let result = [];
+    while (this.token !== this.EOF && this.token !== "}") {
+      const statement = this.read_top_statement();
+      if (statement) {
+        if (Array.isArray(statement)) {
+          result = result.concat(statement);
+        } else {
+          result.push(statement);
+        }
+      }
+    }
+    return result;
+  },
+  /**
+   * reading a top statement
+   * ```ebnf
+   *  top_statement ::=
+   *       namespace | function | class
+   *       | interface | trait
+   *       | use_statements | const_list
+   *       | statement
+   * ```
+   */
+  read_top_statement: function() {
+    switch (this.token) {
+      case this.tok.T_FUNCTION:
+        return this.read_function(false, false);
+      // optional flags
+      case this.tok.T_ABSTRACT:
+      case this.tok.T_FINAL:
+      case this.tok.T_CLASS:
+        return this.read_class();
+      case this.tok.T_INTERFACE:
+        return this.read_interface();
+      case this.tok.T_TRAIT:
+        return this.read_trait();
+      case this.tok.T_USE:
+        return this.read_use_statement();
+      case this.tok.T_CONST: {
+        const result = this.node("constantstatement");
+        const items = this.next().read_const_list();
+        this.expectEndOfStatement();
+        return result(null, items);
+      }
+      case this.tok.T_NAMESPACE:
+        return this.read_namespace();
+      case this.tok.T_HALT_COMPILER: {
+        const result = this.node("halt");
+        if (this.next().expect("(")) this.next();
+        if (this.expect(")")) this.next();
+        this.expect(";");
+        this.lexer.done = true;
+        return result(this.lexer._input.substring(this.lexer.offset));
+      }
+      default:
+        return this.read_statement();
+    }
+  },
+  /**
+   * reads a list of simple inner statements (helper for inner_statement*)
+   * ```ebnf
+   *  inner_statements ::= inner_statement*
+   * ```
+   */
+  read_inner_statements: function() {
+    let result = [];
+    while (this.token != this.EOF && this.token !== "}") {
+      const statement = this.read_inner_statement();
+      if (statement) {
+        if (Array.isArray(statement)) {
+          result = result.concat(statement);
+        } else {
+          result.push(statement);
+        }
+      }
+    }
+    return result;
+  },
+  /**
+   * Reads a list of constants declaration
+   * ```ebnf
+   *   const_list ::= T_CONST T_STRING '=' expr (',' T_STRING '=' expr)* ';'
+   * ```
+   */
+  read_const_list: function() {
+    return this.read_list(
+      function() {
+        this.expect(this.tok.T_STRING);
+        const result = this.node("constant");
+        let constName = this.node("identifier");
+        const name = this.text();
+        this.next();
+        constName = constName(name);
+        if (this.expect("=")) {
+          return result(constName, this.next().read_expr());
+        } else {
+          // fallback
+          return result(constName, null);
+        }
+      },
+      ",",
+      false
+    );
+  },
+  /**
+   * Reads a list of constants declaration
+   * ```ebnf
+   *   declare_list ::= IDENTIFIER '=' expr (',' IDENTIFIER '=' expr)*
+   * ```
+   * @retrurn {Array}
+   */
+  read_declare_list: function() {
+    const result = [];
+    while (this.token != this.EOF && this.token !== ")") {
+      this.expect(this.tok.T_STRING);
+      const directive = this.node("declaredirective");
+      let key = this.node("identifier");
+      const name = this.text();
+      this.next();
+      key = key(name);
+      let value = null;
+      if (this.expect("=")) {
+        value = this.next().read_expr();
+      }
+      result.push(directive(key, value));
+      if (this.token !== ",") break;
+      this.next();
+    }
+    return result;
+  },
+  /**
+   * reads a simple inner statement
+   * ```ebnf
+   *  inner_statement ::= '{' inner_statements '}' | token
+   * ```
+   */
+  read_inner_statement: function() {
+    switch (this.token) {
+      case this.tok.T_FUNCTION:
+        return this.read_function(false, false);
+      // optional flags
+      case this.tok.T_ABSTRACT:
+      case this.tok.T_FINAL:
+      case this.tok.T_CLASS:
+        return this.read_class();
+      case this.tok.T_INTERFACE:
+        return this.read_interface();
+      case this.tok.T_TRAIT:
+        return this.read_trait();
+      case this.tok.T_HALT_COMPILER: {
+        this.raiseError(
+          "__HALT_COMPILER() can only be used from the outermost scope"
+        );
+        // fallback : returns a node but does not stop the parsing
+        let node = this.node("halt");
+        this.next().expect("(") && this.next();
+        this.expect(")") && this.next();
+        node = node(this.lexer._input.substring(this.lexer.offset));
+        this.expect(";") && this.next();
+        return node;
+      }
+      default:
+        return this.read_statement();
+    }
+  },
+  /**
+   * Reads statements
+   */
+  read_statement: function() {
+    switch (this.token) {
+      case "{":
+        return this.read_code_block(false);
+
+      case this.tok.T_IF:
+        return this.read_if();
+
+      case this.tok.T_SWITCH:
+        return this.read_switch();
+
+      case this.tok.T_FOR:
+        return this.read_for();
+
+      case this.tok.T_FOREACH:
+        return this.read_foreach();
+
+      case this.tok.T_WHILE:
+        return this.read_while();
+
+      case this.tok.T_DO:
+        return this.read_do();
+
+      case this.tok.T_COMMENT:
+        return this.read_comment();
+
+      case this.tok.T_DOC_COMMENT:
+        return this.read_doc_comment();
+
+      case this.tok.T_RETURN: {
+        const result = this.node("return");
+        let expr = null;
+        if (!this.next().is("EOS")) {
+          expr = this.read_expr();
+        }
+        this.expectEndOfStatement();
+        return result(expr);
+      }
+
+      // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L429
+      case this.tok.T_BREAK:
+      case this.tok.T_CONTINUE: {
+        const result = this.node(
+          this.token === this.tok.T_CONTINUE ? "continue" : "break"
+        );
+        let level = null;
+        this.next(); // look ahead
+        if (this.token !== ";") {
+          level = this.read_expr();
+        }
+        this.expectEndOfStatement();
+        return result(level);
+      }
+
+      case this.tok.T_GLOBAL: {
+        const result = this.node("global");
+        const items = this.next().read_list(this.read_simple_variable, ",");
+        this.expectEndOfStatement();
+        return result(items);
+      }
+
+      case this.tok.T_STATIC: {
+        const current = [this.token, this.lexer.getState()];
+        const result = this.node();
+        if (this.next().token === this.tok.T_DOUBLE_COLON) {
+          // static keyword for a class
+          this.lexer.tokens.push(current);
+          const expr = this.next().read_expr();
+          this.expectEndOfStatement(expr);
+          return result("expressionstatement", expr);
+        }
+        if (this.token === this.tok.T_FUNCTION) {
+          return this.read_function(true, [0, 1, 0]);
+        }
+        const items = this.read_variable_declarations();
+        this.expectEndOfStatement();
+        return result("static", items);
+      }
+
+      case this.tok.T_ECHO: {
+        const result = this.node("echo");
+        const text = this.text();
+        const shortForm = text === "<?=" || text === "<%=";
+        const expressions = this.next().read_list(this.read_expr, ",");
+        this.expectEndOfStatement();
+        return result(expressions, shortForm);
+      }
+
+      case this.tok.T_INLINE_HTML: {
+        const value = this.text();
+        let prevChar =
+          this.lexer.yylloc.first_offset > 0
+            ? this.lexer._input[this.lexer.yylloc.first_offset - 1]
+            : null;
+        const fixFirstLine = prevChar === "\r" || prevChar === "\n";
+        // revert back the first stripped line
+        if (fixFirstLine) {
+          if (
+            prevChar === "\n" &&
+            this.lexer.yylloc.first_offset > 1 &&
+            this.lexer._input[this.lexer.yylloc.first_offset - 2] === "\r"
+          ) {
+            prevChar = "\r\n";
+          }
+        }
+        const result = this.node("inline");
+        this.next();
+        return result(value, fixFirstLine ? prevChar + value : value);
+      }
+
+      case this.tok.T_UNSET: {
+        const result = this.node("unset");
+        this.next().expect("(") && this.next();
+        const variables = this.read_list(this.read_variable, ",");
+        this.expect(")") && this.next();
+        this.expect(";") && this.next();
+        return result(variables);
+      }
+
+      case this.tok.T_DECLARE: {
+        const result = this.node("declare");
+        const body = [];
+        let mode;
+        this.next().expect("(") && this.next();
+        const directives = this.read_declare_list();
+        this.expect(")") && this.next();
+        if (this.token === ":") {
+          this.next();
+          while (
+            this.token != this.EOF &&
+            this.token !== this.tok.T_ENDDECLARE
+          ) {
+            // @todo : check declare_statement from php / not valid
+            body.push(this.read_top_statement());
+          }
+          this.expect(this.tok.T_ENDDECLARE) && this.next();
+          this.expectEndOfStatement();
+          mode = this.ast.declare.MODE_SHORT;
+        } else if (this.token === "{") {
+          this.next();
+          while (this.token != this.EOF && this.token !== "}") {
+            // @todo : check declare_statement from php / not valid
+            body.push(this.read_top_statement());
+          }
+          this.expect("}") && this.next();
+          mode = this.ast.declare.MODE_BLOCK;
+        } else {
+          this.expect(";") && this.next();
+          mode = this.ast.declare.MODE_NONE;
+        }
+        return result(directives, body, mode);
+      }
+
+      case this.tok.T_TRY:
+        return this.read_try();
+
+      case this.tok.T_THROW: {
+        const result = this.node("throw");
+        const expr = this.next().read_expr();
+        this.expectEndOfStatement();
+        return result(expr);
+      }
+
+      // ignore this (extra ponctuation)
+      case ";": {
+        this.next();
+        return null;
+      }
+
+      case this.tok.T_STRING: {
+        const result = this.node();
+        const current = [this.token, this.lexer.getState()];
+        const label = this.text();
+        // AST : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L457
+        if (this.next().token === ":") {
+          this.next();
+          return result("label", label);
+        }
+
+        // default fallback expr / T_STRING '::' (etc...)
+        result.destroy();
+        this.lexer.tokens.push(current);
+        const statement = this.node("expressionstatement");
+        const expr = this.next().read_expr();
+        this.expectEndOfStatement(expr);
+        return statement(expr);
+      }
+
+      case this.tok.T_GOTO: {
+        const result = this.node("goto");
+        let label = null;
+        if (this.next().expect(this.tok.T_STRING)) {
+          label = this.text();
+          this.next().expectEndOfStatement();
+        }
+        return result(label);
+      }
+
+      default: {
+        // default fallback expr
+        const statement = this.node("expressionstatement");
+        const expr = this.read_expr();
+        this.expectEndOfStatement(expr);
+        return statement(expr);
+      }
+    }
+  },
+  /**
+   * ```ebnf
+   *  code_block ::= '{' (inner_statements | top_statements) '}'
+   * ```
+   */
+  read_code_block: function(top) {
+    const result = this.node("block");
+    this.expect("{") && this.next();
+    const body = top
+      ? this.read_top_statements()
+      : this.read_inner_statements();
+    this.expect("}") && this.next();
+    return result(null, body);
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_switch.js.html b/docs/parser_switch.js.html new file mode 100644 index 000000000..db0a138af --- /dev/null +++ b/docs/parser_switch.js.html @@ -0,0 +1,233 @@ + + + + + + + + + + + parser/switch.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/switch.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * Reads a switch statement
+   * ```ebnf
+   *  switch ::= T_SWITCH '(' expr ')' switch_case_list
+   * ```
+   * @return {Switch}
+   * @see http://php.net/manual/en/control-structures.switch.php
+   */
+  read_switch: function() {
+    const result = this.node("switch");
+    this.expect(this.tok.T_SWITCH) && this.next();
+    this.expect("(") && this.next();
+    const test = this.read_expr();
+    this.expect(")") && this.next();
+    const shortForm = this.token === ":";
+    const body = this.read_switch_case_list();
+    return result(test, body, shortForm);
+  },
+  /**
+   * ```ebnf
+   *  switch_case_list ::= '{' ';'? case_list* '}' | ':' ';'? case_list* T_ENDSWITCH ';'
+   * ```
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L566
+   */
+  read_switch_case_list: function() {
+    // DETECT SWITCH MODE
+    let expect = null;
+    const result = this.node("block");
+    const items = [];
+    if (this.token === "{") {
+      expect = "}";
+    } else if (this.token === ":") {
+      expect = this.tok.T_ENDSWITCH;
+    } else {
+      this.expect(["{", ":"]);
+    }
+    // OPTIONNAL ';'
+    // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L570
+    if (this.next().token === ";") {
+      this.next();
+    }
+    // EXTRACTING CASES
+    while (this.token !== this.EOF && this.token !== expect) {
+      items.push(this.read_case_list(expect));
+    }
+    // CHECK END TOKEN
+    this.expect(expect) && this.next();
+    if (expect === this.tok.T_ENDSWITCH) {
+      this.expectEndOfStatement();
+    }
+    return result(null, items);
+  },
+  /**
+   * ```ebnf
+   *   case_list ::= ((T_CASE expr) | T_DEFAULT) (':' | ';') inner_statement*
+   * ```
+   */
+  read_case_list: function(stopToken) {
+    const result = this.node("case");
+    let test = null;
+    let body = null;
+    const items = [];
+    if (this.token === this.tok.T_CASE) {
+      test = this.next().read_expr();
+    } else if (this.token === this.tok.T_DEFAULT) {
+      // the defaut entry - no condition
+      this.next();
+    } else {
+      this.expect([this.tok.T_CASE, this.tok.T_DEFAULT]);
+    }
+    this.expect([":", ";"]) && this.next();
+    body = this.node("block");
+    while (
+      this.token != this.EOF &&
+      this.token !== stopToken &&
+      this.token !== this.tok.T_CASE &&
+      this.token !== this.tok.T_DEFAULT
+    ) {
+      items.push(this.read_inner_statement());
+    }
+    return result(test, items.length > 0 ? body(null, items) : null);
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_try.js.html b/docs/parser_try.js.html new file mode 100644 index 000000000..0b1dac71f --- /dev/null +++ b/docs/parser_try.js.html @@ -0,0 +1,182 @@ + + + + + + + + + + + parser/try.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/try.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * ```ebnf
+   *  try ::= T_TRY '{' inner_statement* '}'
+   *          (
+   *              T_CATCH '(' namespace_name variable ')' '{'  inner_statement* '}'
+   *          )*
+   *          (T_FINALLY '{' inner_statement* '}')?
+   * ```
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L448
+   * @return {Try}
+   */
+  read_try: function() {
+    this.expect(this.tok.T_TRY);
+    const result = this.node("try");
+    let always = null;
+    const catches = [];
+    const body = this.next().read_statement();
+    // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L455
+    while (this.token === this.tok.T_CATCH) {
+      const item = this.node("catch");
+      this.next().expect("(") && this.next();
+      const what = this.read_list(this.read_namespace_name, "|", false);
+      const variable = this.read_variable(true, false, false);
+      this.expect(")");
+      catches.push(item(this.next().read_statement(), what, variable));
+    }
+    if (this.token === this.tok.T_FINALLY) {
+      always = this.next().read_statement();
+    }
+    return result(body, catches, always);
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_utils.js.html b/docs/parser_utils.js.html new file mode 100644 index 000000000..efead6ba8 --- /dev/null +++ b/docs/parser_utils.js.html @@ -0,0 +1,260 @@ + + + + + + + + + + + parser/utils.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/utils.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * Reads a short form of tokens
+   * @param {Number} token - The ending token
+   * @return {Block}
+   */
+  read_short_form: function(token) {
+    const body = this.node("block");
+    const items = [];
+    if (this.expect(":")) this.next();
+    while (this.token != this.EOF && this.token !== token) {
+      items.push(this.read_inner_statement());
+    }
+    if (this.expect(token)) this.next();
+    this.expectEndOfStatement();
+    return body(null, items);
+  },
+
+  /**
+   * Helper : reads a list of tokens / sample : T_STRING ',' T_STRING ...
+   * ```ebnf
+   * list ::= separator? ( item separator )* item
+   * ```
+   */
+  read_list: function(item, separator, preserveFirstSeparator) {
+    const result = [];
+
+    if (this.token == separator) {
+      if (preserveFirstSeparator) {
+        result.push(typeof item === "function" ? this.node("noop")() : null);
+      }
+      this.next();
+    }
+
+    if (typeof item === "function") {
+      do {
+        result.push(item.apply(this, []));
+        if (this.token != separator) {
+          break;
+        }
+      } while (this.next().token != this.EOF);
+    } else {
+      if (this.expect(item)) {
+        result.push(this.text());
+      } else {
+        return [];
+      }
+      while (this.next().token != this.EOF) {
+        if (this.token != separator) break;
+        // trim current separator & check item
+        if (this.next().token != item) break;
+        result.push(this.text());
+      }
+    }
+    return result;
+  },
+
+  /**
+   * Reads a list of names separated by a comma
+   *
+   * ```ebnf
+   * name_list ::= namespace (',' namespace)*
+   * ```
+   *
+   * Sample code :
+   * ```php
+   * <?php class foo extends bar, baz { }
+   * ```
+   *
+   * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L726
+   * @return {Reference[]}
+   */
+  read_name_list: function() {
+    return this.read_list(this.read_namespace_name, ",", false);
+  },
+
+  /**
+   * Reads a list of variables declarations
+   *
+   * ```ebnf
+   * variable_declaration ::= T_VARIABLE ('=' expr)?*
+   * variable_declarations ::= variable_declaration (',' variable_declaration)*
+   * ```
+   *
+   * Sample code :
+   * ```php
+   * <?php static $a = 'hello', $b = 'world';
+   * ```
+   * @return {StaticVariable[]} Returns an array composed by a list of variables, or
+   * assign values
+   */
+  read_variable_declarations: function() {
+    return this.read_list(function() {
+      const node = this.node("staticvariable");
+      let variable = this.node("variable");
+      // plain variable name
+      if (this.expect(this.tok.T_VARIABLE)) {
+        const name = this.text().substring(1);
+        this.next();
+        variable = variable(name, false, false);
+      } else {
+        variable = variable("#ERR", false, false);
+      }
+      if (this.token === "=") {
+        return node(variable, this.next().read_expr());
+      } else {
+        return variable;
+      }
+    }, ",");
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/parser_variable.js.html b/docs/parser_variable.js.html new file mode 100644 index 000000000..5b7efec55 --- /dev/null +++ b/docs/parser_variable.js.html @@ -0,0 +1,499 @@ + + + + + + + + + + + parser/variable.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ parser/variable.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+module.exports = {
+  /**
+   * Reads a variable
+   *
+   * ```ebnf
+   *   variable ::= &? ...complex @todo
+   * ```
+   *
+   * Some samples of parsed code :
+   * ```php
+   *  &$var                      // simple var
+   *  $var                      // simple var
+   *  classname::CONST_NAME     // dynamic class name with const retrieval
+   *  foo()                     // function call
+   *  $var->func()->property    // chained calls
+   * ```
+   */
+  read_variable: function(read_only, encapsed, byref) {
+    let result;
+
+    // check the byref flag
+    if (!byref && this.token === "&") {
+      byref = true;
+      this.next();
+    }
+
+    // reads the entry point
+    if (this.is([this.tok.T_VARIABLE, "$"])) {
+      result = this.read_reference_variable(encapsed, byref);
+    } else if (
+      this.is([
+        this.tok.T_NS_SEPARATOR,
+        this.tok.T_STRING,
+        this.tok.T_NAMESPACE
+      ])
+    ) {
+      result = this.node();
+      const name = this.read_namespace_name();
+      if (
+        this.token != this.tok.T_DOUBLE_COLON &&
+        this.token != "(" &&
+        ["parentreference", "selfreference"].indexOf(name.kind) === -1
+      ) {
+        // @see parser.js line 130 : resolves a conflict with scalar
+        const literal = name.name.toLowerCase();
+        if (literal === "true") {
+          result = name.destroy(result("boolean", true, name.name));
+        } else if (literal === "false") {
+          result = name.destroy(result("boolean", false, name.name));
+        } else {
+          // @todo null keyword ?
+          result = result("identifier", name);
+        }
+      } else {
+        // @fixme possible #193 bug
+        result.destroy(name);
+        result = name;
+      }
+    } else if (this.token === this.tok.T_STATIC) {
+      result = this.node("staticreference");
+      const raw = this.text();
+      this.next();
+      result = result(raw);
+    } else {
+      this.expect("VARIABLE");
+    }
+
+    // static mode
+    if (this.token === this.tok.T_DOUBLE_COLON) {
+      result = this.read_static_getter(result, encapsed);
+    }
+
+    return this.recursive_variable_chain_scan(result, read_only, encapsed);
+  },
+
+  // resolves a static call
+  read_static_getter: function(what, encapsed) {
+    const result = this.node("staticlookup");
+    let offset, name;
+    if (this.next().is([this.tok.T_VARIABLE, "$"])) {
+      offset = this.read_reference_variable(encapsed, false);
+    } else if (
+      this.token === this.tok.T_STRING ||
+      this.token === this.tok.T_CLASS ||
+      (this.php7 && this.is("IDENTIFIER"))
+    ) {
+      offset = this.node("identifier");
+      name = this.text();
+      this.next();
+      offset = offset(name);
+    } else if (this.token === "{") {
+      offset = this.node("literal");
+      name = this.next().read_expr();
+      this.expect("}") && this.next();
+      offset = offset("literal", name, null);
+      this.expect("(");
+    } else {
+      this.error([this.tok.T_VARIABLE, this.tok.T_STRING]);
+      // graceful mode : set getter as error node and continue
+      offset = this.node("identifier");
+      name = this.text();
+      this.next();
+      offset = offset(name);
+    }
+    return result(what, offset);
+  },
+
+  read_what: function(is_static_lookup = false) {
+    let what = null;
+    let name = null;
+    switch (this.next().token) {
+      case this.tok.T_STRING:
+        what = this.node("identifier");
+        name = this.text();
+        this.next();
+        what = what(name);
+
+        if (is_static_lookup && this.token === this.tok.T_OBJECT_OPERATOR) {
+          this.error();
+        }
+
+        if (this.token === this.tok.T_VARIABLE) {
+          const inner = this.node("variable");
+          name = this.text().substring(1);
+          this.next();
+          what = this.node("encapsed")(
+            [what, inner(name, false, false)],
+            null,
+            "offset"
+          );
+          if (what.loc && what.value[0].loc) {
+            what.loc.start = what.value[0].loc.start;
+          }
+        } else if (this.token === "{") {
+          const expr = this.next().read_expr();
+          this.expect("}") && this.next();
+          what = this.node("encapsed")([what, expr], null, "offset");
+          if (what.loc && what.value[0].loc) {
+            what.loc.start = what.value[0].loc.start;
+          }
+        }
+        break;
+      case this.tok.T_VARIABLE:
+        what = this.node("variable");
+        name = this.text().substring(1);
+        this.next();
+        what = what(name, false, false);
+        break;
+      case "$":
+        what = this.node();
+        this.next().expect(["$", "{", this.tok.T_VARIABLE]);
+        if (this.token === "{") {
+          // $obj->${$varname}
+          name = this.next().read_expr();
+          this.expect("}") && this.next();
+          what = what("literal", "literal", name, null);
+        } else {
+          // $obj->$$varname
+          name = this.read_expr();
+          what = what("variable", name, false, false);
+        }
+        break;
+      case "{":
+        what = this.node("literal");
+        name = this.next().read_expr();
+        this.expect("}") && this.next();
+        what = what("literal", name, null);
+        break;
+      default:
+        this.error([this.tok.T_STRING, this.tok.T_VARIABLE, "$", "{"]);
+        // graceful mode : set what as error mode & continue
+        what = this.node("identifier");
+        name = this.text();
+        this.next();
+        what = what(name);
+        break;
+    }
+
+    return what;
+  },
+
+  recursive_variable_chain_scan: function(result, read_only, encapsed) {
+    let node, offset;
+    recursive_scan_loop: while (this.token != this.EOF) {
+      switch (this.token) {
+        case "(":
+          if (read_only) {
+            // @fixme : add more informations & test
+            return result;
+          } else {
+            result = this.node("call")(
+              result,
+              this.read_function_argument_list()
+            );
+          }
+          break;
+        case "[":
+          node = this.node("offsetlookup");
+          this.next();
+          offset = false;
+          if (encapsed) {
+            offset = this.read_encaps_var_offset();
+            this.expect("]") && this.next();
+          } else {
+            // callable_variable : https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L1122
+            if (this.token !== "]") {
+              offset = this.read_expr();
+              this.expect("]") && this.next();
+            } else {
+              this.next();
+            }
+          }
+          result = node(result, offset);
+          break;
+        case this.tok.T_DOUBLE_COLON:
+          // @see https://github.com/glayzzle/php-parser/issues/107#issuecomment-354104574
+          if (
+            result.kind === "staticlookup" &&
+            result.offset.kind === "identifier"
+          ) {
+            this.error();
+          }
+
+          node = this.node("staticlookup");
+          result = node(result, this.read_what(true));
+
+          // fix 185
+          // static lookup dereferencables are limited to staticlookup over functions
+          /*if (dereferencable && this.token !== "(") {
+            this.error("(");
+          }*/
+          break;
+        case this.tok.T_OBJECT_OPERATOR: {
+          node = this.node("propertylookup");
+          result = node(result, this.read_what());
+          break;
+        }
+        default:
+          break recursive_scan_loop;
+      }
+    }
+    return result;
+  },
+  /**
+   * https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L1231
+   */
+  read_encaps_var_offset: function() {
+    let offset = this.node();
+    if (this.token === this.tok.T_STRING) {
+      const text = this.text();
+      this.next();
+      offset = offset("identifier", text);
+    } else if (this.token === this.tok.T_NUM_STRING) {
+      const num = this.text();
+      this.next();
+      offset = offset("number", num, null);
+    } else if (this.token === this.tok.T_VARIABLE) {
+      const name = this.text().substring(1);
+      this.next();
+      offset = offset("variable", name, false, false);
+    } else {
+      this.expect([
+        this.tok.T_STRING,
+        this.tok.T_NUM_STRING,
+        this.tok.T_VARIABLE
+      ]);
+      // fallback : consider as identifier
+      const text = this.text();
+      this.next();
+      offset = offset("identifier", text);
+    }
+    return offset;
+  },
+  /**
+   * ```ebnf
+   *  reference_variable ::=  simple_variable ('[' OFFSET ']')* | '{' EXPR '}'
+   * ```
+   * <code>
+   *  $foo[123];      // foo is an array ==> gets its entry
+   *  $foo{1};        // foo is a string ==> get the 2nd char offset
+   *  ${'foo'}[123];  // get the dynamic var $foo
+   *  $foo[123]{1};   // gets the 2nd char from the 123 array entry
+   * </code>
+   */
+  read_reference_variable: function(encapsed, byref) {
+    let result = this.read_simple_variable(byref);
+    let offset;
+    while (this.token != this.EOF) {
+      const node = this.node();
+      if (this.token == "{" && !encapsed) {
+        // @fixme check coverage, not sure thats working
+        offset = this.next().read_expr();
+        this.expect("}") && this.next();
+        result = node("offsetlookup", result, offset);
+      } else {
+        node.destroy();
+        break;
+      }
+    }
+    return result;
+  },
+  /**
+   * ```ebnf
+   *  simple_variable ::= T_VARIABLE | '$' '{' expr '}' | '$' simple_variable
+   * ```
+   */
+  read_simple_variable: function(byref) {
+    let result = this.node("variable");
+    let name;
+    if (
+      this.expect([this.tok.T_VARIABLE, "$"]) &&
+      this.token === this.tok.T_VARIABLE
+    ) {
+      // plain variable name
+      name = this.text().substring(1);
+      this.next();
+      result = result(name, byref, false);
+    } else {
+      if (this.token === "$") this.next();
+      // dynamic variable name
+      switch (this.token) {
+        case "{": {
+          const expr = this.next().read_expr();
+          this.expect("}") && this.next();
+          result = result(expr, byref, true);
+          break;
+        }
+        case "$": // $$$var
+          // @fixme check coverage here
+          result = result(this.read_simple_variable(false), byref, false);
+          break;
+        case this.tok.T_VARIABLE: {
+          // $$var
+          name = this.text().substring(1);
+          const node = this.node("variable");
+          this.next();
+          result = result(node(name, false, false), byref, false);
+          break;
+        }
+        default:
+          this.error(["{", "$", this.tok.T_VARIABLE]);
+          // graceful mode
+          name = this.text();
+          this.next();
+          result = result(name, byref, false);
+      }
+    }
+    return result;
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/scripts/linenumber.js b/docs/scripts/linenumber.js new file mode 100644 index 000000000..ff6c0693b --- /dev/null +++ b/docs/scripts/linenumber.js @@ -0,0 +1,24 @@ +'use strict'; + +/* global document */ +(function () { + var lineId, lines, totalLines, anchorHash; + var source = document.getElementsByClassName('prettyprint source linenums'); + var i = 0; + var lineNumber = 0; + + if (source && source[0]) { + anchorHash = document.location.hash.substring(1); + lines = source[0].getElementsByTagName('li'); + totalLines = lines.length; + + for (; i < totalLines; i++) { + lineNumber++; + lineId = 'line' + lineNumber; + lines[i].id = lineId; + if (lineId === anchorHash) { + lines[i].className += ' selected'; + } + } + } +})(); diff --git a/docs/scripts/pagelocation.js b/docs/scripts/pagelocation.js new file mode 100644 index 000000000..e1383680c --- /dev/null +++ b/docs/scripts/pagelocation.js @@ -0,0 +1,89 @@ +'use strict'; + +$(document).ready(function () { + var currentSectionNav, target; + + // If an anchor hash is in the URL highlight the menu item + highlightActiveHash(); + // If a specific page section is in the URL highlight the menu item + highlightActiveSection(); + + // If a specific page section is in the URL scroll that section up to the top + currentSectionNav = $('#' + getCurrentSectionName() + '-nav'); + + if (currentSectionNav.position()) { + $('nav').scrollTop(currentSectionNav.position().top); + } + + // function to scroll to anchor when clicking an anchor linl + $('a[href*="#"]:not([href="#"])').click(function () { + /* eslint-disable no-invalid-this */ + if (location.pathname.replace(/^\//, '') === this.pathname.replace(/^\//, '') && location.hostname === this.hostname) { + target = $(this.hash); + target = target.length ? target : $('[name=' + this.hash.slice(1) + ']'); + if (target.length) { + $('html, body').animate({ + scrollTop: target.offset().top + }, 1000); + } + } + /* eslint-enable no-invalid-this */ + }); +}); + +// If a new anchor section is selected, change the hightlighted menu item +$(window).bind('hashchange', function (event) { + highlightActiveHash(event); +}); + +function highlightActiveHash(event) { + var oldUrl, oldSubSectionElement; + + // check for and remove old hash active state + if (event && event.originalEvent.oldURL) { + oldUrl = event.originalEvent.oldURL; + + if (oldUrl.indexOf('#') > -1) { + oldSubSectionElement = $('#' + getCurrentSectionName() + '-' + oldUrl.substring(oldUrl.indexOf('#') + 1) + '-nav'); + + if (oldSubSectionElement) { + oldSubSectionElement.removeClass('active'); + } + } + } + + if (getCurrentHashName()) { + $('#' + getCurrentSectionName() + '-' + getCurrentHashName() + '-nav').addClass('active'); + } +} + +function highlightActiveSection() { + var pageId = getCurrentSectionName(); + + $('#' + pageId + '-nav').addClass('active'); +} + +function getCurrentSectionName() { + var path = window.location.pathname; + var pageUrl = path.split('/').pop(); + + var sectionName = pageUrl.substring(0, pageUrl.indexOf('.')); + + // remove the wodr module- if its in the url + sectionName = sectionName.replace('module-', ''); + + return sectionName; +} + +function getCurrentHashName() { + var pageSubSectionId; + var pageSubSectionHash = window.location.hash; + + if (pageSubSectionHash) { + pageSubSectionId = pageSubSectionHash.substring(1).replace('.', ''); + + return pageSubSectionId; + } + + return false; +} diff --git a/docs/styles/collapse.css b/docs/styles/collapse.css new file mode 100644 index 000000000..4dc412147 --- /dev/null +++ b/docs/styles/collapse.css @@ -0,0 +1,27 @@ +@media only screen and (min-width: 681px) { + nav > ul > li:hover .methods, + .active .methods { + display: block; + } + + .methods { + display: none; + } + + nav > ul > li { + padding: 20px 0; + } + + nav > ul > li > a { + padding: 0; + } + + nav > ul > li.active a { + margin-bottom: 10px; + } + + nav > ul > li:hover > a, + nav > ul > li.active > a { + margin-bottom: 15px; + } +} diff --git a/docs/styles/jsdoc-default.css b/docs/styles/jsdoc-default.css new file mode 100644 index 000000000..c873f1914 --- /dev/null +++ b/docs/styles/jsdoc-default.css @@ -0,0 +1,953 @@ +@font-face { + font-family: "Avenir Next W01"; + font-style: normal; + font-weight: 600; + src: url("https://fast.fonts.net/dv2/14/14c73713-e4df-4dba-933b-057feeac8dd1.woff2?d44f19a684109620e484167ba790e8180fd9e29df91d80ce3d096f014db863074e1ea706cf5ed4e1c042492e76df291ce1d24ec684d3d9da9684f55406b9f22bce02f0f30f556681593dafea074d7bd44e28a680d083ccfd44ed4f8a3087a20c56147c11f917ed1dbd85c4a18cf38da25e6ac78f008f472262304d50e7e0cb7541ef1642c676db6e4bde4924846f5daf486fbde9335e98f6a20f6664bc4525253d1d4fca42cf1c490483c8daf0237f6a0fd292563417ad80ca3e69321417747bdc6f0969f34b2a0401b5e2b9a4dfd5b06d9710850900c66b34870aef&projectId=f750d5c7-baa2-4767-afd7-45484f47fe17") format('woff2'); +} + +@font-face { + font-family: "Avenir Next W01"; + font-style: normal; + font-weight: 500; + src: url("https://fast.fonts.net/dv2/14/627fbb5a-3bae-4cd9-b617-2f923e29d55e.woff2?d44f19a684109620e484167ba790e8180fd9e29df91d80ce3d096f014db863074e1ea706cf5ed4e1c042492e76df291ce1d24ec684d3d9da9684f55406b9f22bce02f0f30f556681593dafea074d7bd44e28a680d083ccfd44ed4f8a3087a20c56147c11f917ed1dbd85c4a18cf38da25e6ac78f008f472262304d50e7e0cb7541ef1642c676db6e4bde4924846f5daf486fbde9335e98f6a20f6664bc4525253d1d4fca42cf1c490483c8daf0237f6a0fd292563417ad80ca3e69321417747bdc6f0969f34b2a0401b5e2b9a4dfd5b06d9710850900c66b34870aef&projectId=f750d5c7-baa2-4767-afd7-45484f47fe17") format('woff2'); +} + +@font-face { + font-family: "Avenir Next W01"; + font-style: normal; + font-weight: 400; + src: url("https://fast.fonts.net/dv2/14/2cd55546-ec00-4af9-aeca-4a3cd186da53.woff2?d44f19a684109620e484167ba790e8180fd9e29df91d80ce3d096f014db863074e1ea706cf5ed4e1c042492e76df291ce1d24ec684d3d9da9684f55406b9f22bce02f0f30f556681593dafea074d7bd44e28a680d083ccfd44ed4f8a3087a20c56147c11f917ed1dbd85c4a18cf38da25e6ac78f008f472262304d50e7e0cb7541ef1642c676db6e4bde4924846f5daf486fbde9335e98f6a20f6664bc4525253d1d4fca42cf1c490483c8daf0237f6a0fd292563417ad80ca3e69321417747bdc6f0969f34b2a0401b5e2b9a4dfd5b06d9710850900c66b34870aef&projectId=f750d5c7-baa2-4767-afd7-45484f47fe17") format('woff2'); +} + +@font-face { + font-family: 'bt_mono'; + font-style: normal; + font-weight: 400; + src: url('https://assets.braintreegateway.com/fonts/bt_mono_regular-webfont.eot'); + src: url('https://assets.braintreegateway.com/fonts/bt_mono_regular-webfont.woff2') format('woff2'), url('https://assets.braintreegateway.com/fonts/bt_mono_regular-webfont.woff') format('woff'), url('https://assets.braintreegateway.com/fonts/bt_mono_regular-webfont.ttf') format('truetype'), url('https://assets.braintreegateway.com/fonts/bt_mono_regular-webfont.svg#bt_mono_reqular-webfont') format('svg'); +} + +@font-face { + font-family: 'bt_mono'; + font-style: normal; + font-weight: 500; + src: url('https://assets.braintreegateway.com/fonts/bt_mono_medium-webfont.eot'); + src: url('https://assets.braintreegateway.com/fonts/bt_mono_medium-webfont.woff2') format('woff2'), url('https://assets.braintreegateway.com/fonts/bt_mono_medium-webfont.woff') format('woff'), url('https://assets.braintreegateway.com/fonts/bt_mono_medium-webfont.ttf') format('truetype'), url('https://assets.braintreegateway.com/fonts/bt_mono_medium-webfont.svg#bt_mono_medium-webfont') format('svg'); +} + +@font-face { + font-family: 'bt_mono'; + font-style: normal; + font-weight: 600; + src: url('https://assets.braintreegateway.com/fonts/bt_mono_bold-webfont.eot'); + src: url('https://assets.braintreegateway.com/fonts/bt_mono_bold-webfont.woff2') format('woff2'), url('https://assets.braintreegateway.com/fonts/bt_mono_bold-webfont.woff') format('woff'), url('https://assets.braintreegateway.com/fonts/bt_mono_bold-webfont.ttf') format('truetype'), url('https://assets.braintreegateway.com/fonts/bt_mono_bold-webfont.svg#bt_mono_bold-webfont') format('svg'); +} + +@font-face { + font-family: 'bt_mono'; + font-style: normal; + font-weight: 900; + src: url('https://assets.braintreegateway.com/fonts/bt_mono_heavy-webfont.eot'); + src: url('https://assets.braintreegateway.com/fonts/bt_mono_heavy-webfont.woff2') format('woff2'), url('https://assets.braintreegateway.com/fonts/bt_mono_heavy-webfont.woff') format('woff'), url('https://assets.braintreegateway.com/fonts/bt_mono_heavy-webfont.ttf') format('truetype'), url('https://assets.braintreegateway.com/fonts/bt_mono_heavy-webfont.svg#bt_mono_heavy-webfont') format('svg'); +} + +* { + box-sizing: border-box +} + +html, body { + height: 100%; + width: 100%; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: #3e3c42; + text-rendering: optimizeLegibility; + margin: 0; +} + +body { + color: #3e3c42; + background-color: #f3f3f3; + width: 100%; + font: 16px/1.875 "Avenir Next W01", "Avenir Next", "Helvetica Neue", Helvetica, sans-serif; + font-size: 16px; + line-height: 160%; +} + +a, a:active { + color: #0095dd; + text-decoration: none; +} + +a:hover { + text-decoration: underline +} + +p, ul, ol, blockquote { + margin-bottom: 1em; +} + +p { + max-width: 800px; +} + +h1, h2, h3, h4, h5, h6 { + color: #706d77; + font-weight: 500; + margin: 0; + line-height: 1; +} + +h1 { + color: #4b484f; + font-weight: 500; + font-size: 40px; + display: block; +} + +h1 span { + color: #999; + font-size: 32px; + display: block; + line-height: 1.5; +} + +h1.page-title { + border-bottom: 1px dashed #ccc; + margin-bottom: 20px; + padding-bottom: 30px; +} + +h2 { + font-size: 30px; + margin: 1.5em 0 0; +} + +h3 { + font-size: 20px; + margin: 1.5em 0 0; + text-transform: uppercase; +} + +h3.reference-title { + display: block; + font-weight: 400; + margin-top: 2em; + max-width: 200px; +} + +h3.reference-title small { + display: inline-block; + color: #0095dd; + margin-left: 5px; + font-weight: 500; +} + +h3.subsection-title { + border-bottom: 1px solid #ececec; + padding-bottom: 20px; + margin-top: 3em; + margin-bottom: 1em; +} + +h4 { + font-size: 16px; + margin: 1em 0 0; + font-weight: bold; +} + +h4.name { + font-size: 20px; + margin-top: 0; + font-weight: 500; +} + +h5 { + margin: 2em 0 0.5em 0; + font-size: 14px; + font-weight: 500; + text-transform: uppercase; +} + +.container-overview .subsection-title { + font-size: 14px; + text-transform: uppercase; + margin: 8px 0 15px 0; + font-weight: bold; + color: #4D4E53; + padding-top: 10px; +} + +h6 { + font-size: 100%; + letter-spacing: -0.01em; + margin: 6px 0 3px 0; + font-style: italic; + text-transform: uppercase; + font-weight: 500; +} + +tt, code, kbd, samp { + font-family: "Source Code Pro", monospace; + background: #f4f4f4; + padding: 1px 5px; + border-radius: 5px; +} + +.class-description { + margin-bottom: 1em; + margin-top: 1em; + padding: 10px 20px; + background-color: rgba(26, 159, 224, 0.1); +} + +.class-description:empty { + margin: 0 +} + +#main { + background-color: white; + float: right; + min-width: 360px; + width: calc(100% - 300px); + padding: 30px; + z-index: 100; +} + +header { + display: block; + max-width: 1400px; +} + +section { + display: block; + max-width: 1400px; + background-color: #fff; +} + +.variation { + display: none +} + +.signature-attributes { + font-size: 60%; + color: #aaa; + font-style: italic; + font-weight: lighter; +} + +.rule { + width: 100%; + margin-top: 20px; + display: block; + border-top: 1px solid #ccc; +} + +ul { + list-style-type: none; + padding-left: 0; +} + +ul li a { + font-weight: 500; +} + +ul ul { + padding-top: 5px; +} + +ul li ul { + padding-left: 20px; +} + +ul li ul li a { + font-weight: normal; +} + +nav { + float: left; + display: block; + width: 300px; + background: #f7f7f7; + overflow-x: visible; + overflow-y: auto; + height: 100%; + padding: 0px 30px 100px 30px; + height: 100%; + position: fixed; + transition: left 0.2s; + z-index: 998; + margin-top: 0px; + top: 43px; +} + +.navicon-button { + display: inline-block; + position: fixed; + bottom: 1.5em; + right: 1.5em; + z-index: 2; +} + +nav h3 { + font-size: 13px; + text-transform: uppercase; + letter-spacing: 1px; + font-weight: bold; + line-height: 24px; + margin: 40px 0 10px 0; + padding: 0; +} + +nav ul { + font-size: 100%; + line-height: 17px; + padding: 0; + margin: 0; + list-style-type: none; + border: none; + padding-left: 0; +} + +nav ul a { + font-size: 16px; +} + +nav ul a, nav ul a:active { + display: block; +} + +nav ul a:hover, nav ul a:active { + color: hsl(200, 100%, 43%); + text-decoration: none; +} + +nav>ul { + padding: 0 10px; +} + +nav>ul li:first-child { + padding-top: 0; +} + +nav ul li ul { + padding-left: 0; +} + +nav>ul>li { + border-bottom: 1px solid #e2e2e2; + padding: 10px 0 20px 0; +} + +nav>ul>li.active ul { + border-left: 3px solid #0095dd; + padding-left: 15px; +} + +nav>ul>li.active ul li.active a { + font-weight: bold; +} + +nav>ul>li.active a { + color: #0095dd; +} + +nav>ul>li>a { + color: #706d77; + padding: 20px 0; + font-size: 18px; +} + +nav ul ul { + margin-bottom: 10px; + padding-left: 0; +} + +nav ul ul a { + color: #5f5c63; +} + +nav ul ul a, nav ul ul a:active { + font-family: 'bt_mono', monospace; + font-size: 14px; + padding-left: 20px; + padding-top: 3px; + padding-bottom: 9px; +} + +nav h2 { + font-size: 12px; + margin: 0; + padding: 0; +} + +nav>h2>a { + color: hsl(202, 71%, 50%); + border-bottom: 1px solid hsl(202, 71%, 50%); + padding-bottom: 5px; +} + +nav>h2>a:hover { + font-weight: 500; + text-decoration: none; +} + +footer { + background-color: #fff; + color: hsl(0, 0%, 28%); + margin-left: 300px; + display: block; + font-style: italic; + font-size: 12px; + padding: 30px; + text-align: center; +} + +.ancestors { + color: #999; +} + +.ancestors a { + color: #999 !important; + text-decoration: none; +} + +.clear { + clear: both; +} + +.important { + font-weight: bold; + color: #950B02; +} + +.yes-def { + text-indent: -1000px; +} + +.type-signature { + color: #aaa; +} + +.name, .signature { + font-family: 'bt_mono', monospace; + word-wrap: break-word; +} + +.details { + margin-top: 14px; + font-size: 13px; + text-align: right; + background: #ffffff; + /* Old browsers */ + background: -moz-linear-gradient(left, #ffffff 0%, #fafafa 100%); + /* FF3.6-15 */ + background: -webkit-linear-gradient(left, #ffffff 0%, #fafafa 100%); + /* Chrome10-25,Safari5.1-6 */ + background: linear-gradient(to right, #ffffff 0%, #fafafa 100%); + /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ + filter: progid: DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#fafafa', GradientType=1); + padding-right: 5px; +} + +.details dt { + display: inline-block; +} + +.details dd { + display: inline-block; + margin: 0; +} + +.details dd a { + font-style: italic; + font-weight: normal; + line-height: 1; +} + +.details ul { + list-style-type: none; + margin: 0; +} + +.details pre.prettyprint { + margin: 0 +} + +.details .object-value { + padding-top: 0 +} + +.description { + margin-bottom: 1em; + margin-top: 1em; +} + +.code-caption { + font-style: italic; + margin: 0; + font-size: 16px; + color: #545454; +} + +.prettyprint { + font-size: 13px; + border: 1px solid #ddd; + border-radius: 3px; + overflow: auto; + background-color: #fbfbfb; +} + +.prettyprint.source { + width: inherit; +} + +.prettyprint code { + font-size: 100%; + line-height: 18px; + display: block; + margin: 0 30px; + background-color: #fbfbfb; + color: #4D4E53; +} + +.prettyprint>code { + padding: 30px 15px; +} + +.prettyprint .linenums code { + padding: 0 15px; +} + +.prettyprint .linenums li:first-of-type code { + padding-top: 15px; +} + +.prettyprint code span.line { + display: inline-block; +} + +.prettyprint.linenums { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.prettyprint.linenums ol { + padding-left: 0 +} + +.prettyprint.linenums li { + border-left: 3px #ddd solid +} + +.prettyprint.linenums li.selected, .prettyprint.linenums li.selected * { + background-color: lightyellow +} + +.prettyprint.linenums li * { + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.readme .prettyprint { + max-width: 800px; +} + +.params, .props { + border-spacing: 0; + border: 1px solid #ddd; + border-radius: 3px; + width: 100%; + font-size: 14px; +} + +.params .name, .props .name, .name code { + color: #4D4E53; + font-family: 'bt_mono', monospace; + font-size: 100%; +} + +.params td, .params th, .props td, .props th { + margin: 0px; + text-align: left; + vertical-align: top; + padding: 10px; + display: table-cell; +} + +.params td { + border-top: 1px solid #eee; +} + +.params thead tr, .props thead tr { + background-color: #fff; + font-weight: bold; +} + +.params .params thead tr, .props .props thead tr { + background-color: #fff; + font-weight: bold; +} + +.params td.description>p:first-child, .props td.description>p:first-child { + margin-top: 0; + padding-top: 0; +} + +.params td.description>p:last-child, .props td.description>p:last-child { + margin-bottom: 0; + padding-bottom: 0; +} + +dl.param-type { + margin-top: 5px; +} + +.param-type dt, .param-type dd { + display: inline-block +} + +.param-type dd { + font-family: Consolas, Monaco, 'Andale Mono', monospace +} + +.disabled { + color: #454545 +} + + +/* tag source style */ + +.tag-deprecated { + padding-right: 5px; +} + +.tag-source { + border-bottom: 1px solid rgba(28, 160, 224, 0.35); +} + +.tag-source:first-child { + border-bottom: 1px solid rgba(28, 160, 224, 1); +} + + +/* navicon button */ + +.navicon-button { + position: relative; + transition: 0.25s; + cursor: pointer; + user-select: none; + opacity: .8; + background-color: white; + border-radius: 100%; + width: 50px; + height: 50px; + -webkit-box-shadow: 0px 2px 9px 0px rgba(0, 0, 0, 0.31); + -moz-box-shadow: 0px 2px 9px 0px rgba(0, 0, 0, 0.31); + box-shadow: 0px 2px 9px 0px rgba(0, 0, 0, 0.31); +} + +.navicon-button .navicon:before, .navicon-button .navicon:after { + transition: 0.25s; +} + +.navicon-button:hover { + transition: 0.5s; + opacity: 1; +} + +.navicon-button:hover .navicon:before, .navicon-button:hover .navicon:after { + transition: 0.25s; +} + +.navicon-button:hover .navicon:before { + top: .425rem; +} + +.navicon-button:hover .navicon:after { + top: -.425rem; +} + + +/* navicon */ + +.navicon { + position: relative; + width: 1.5em; + height: .195rem; + background: #000; + top: calc(50% - .09rem); + left: calc(50% - .75rem); + transition: 0.3s; + border-radius: 5px; +} + +.navicon:before, .navicon:after { + display: block; + content: ""; + height: .195rem; + width: 1.5rem; + background: #000; + position: absolute; + z-index: -1; + transition: 0.3s 0.25s; +} + +.navicon:before { + top: 0.425rem; + height: .195rem; + border-radius: 5px; +} + +.navicon:after { + top: -0.425rem; + border-radius: 5px; +} + + +/* open */ + +.nav-trigger:checked+label:not(.steps) .navicon:before, .nav-trigger:checked+label:not(.steps) .navicon:after { + top: 0 !important; +} + +.nav-trigger:checked+label .navicon:before, .nav-trigger:checked+label .navicon:after { + transition: 0.5s; +} + + +/* Minus */ + +.nav-trigger:checked+label { + transform: scale(0.75); +} + + +/* × and + */ + +.nav-trigger:checked+label.plus .navicon, .nav-trigger:checked+label.x .navicon { + background: transparent; +} + +.nav-trigger:checked+label.plus .navicon:before, .nav-trigger:checked+label.x .navicon:before { + transform: rotate(-45deg); + background: #000; +} + +.nav-trigger:checked+label.plus .navicon:after, .nav-trigger:checked+label.x .navicon:after { + transform: rotate(45deg); + background: #000; +} + +.nav-trigger:checked+label.plus { + transform: scale(0.75) rotate(45deg); +} + +.nav-trigger:checked~nav { + left: 0 !important; +} + +.nav-trigger:checked~.overlay { + display: block; +} + +.nav-trigger { + position: fixed; + top: 0; + clip: rect(0, 0, 0, 0); +} + +.overlay { + display: none; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; + background: hsla(0, 0%, 0%, 0.5); + z-index: 1; +} + +table { + border-collapse: separate; + ; + display: block; + overflow-x: auto; + /*table-layout:fixed;*/ +} + +table tbody td { + border-top: 1px solid hsl(207, 10%, 86%); + border-right: 1px solid #eee; + padding: 5px; + /*word-wrap: break-word;*/ +} + +td table.params, td table.props { + border: 0; +} + +@media only screen and (min-width: 320px) and (max-width: 680px) { + body { + overflow-x: hidden; + } + #main { + padding: 30px 30px; + width: 100%; + min-width: 360px; + } + nav { + background: #FFF; + width: 300px; + height: 100%; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: -300px; + z-index: 3; + padding: 0 10px; + transition: left 0.2s; + margin-top: 0; + } + .navicon-button { + display: inline-block; + position: fixed; + bottom: 1.5em; + right: 20px; + z-index: 1000; + } + .top-nav-wrapper { + display: none; + } + #main h1.page-title { + margin: 0.5em 0; + } + footer { + margin-left: 0; + margin-bottom: 30px; + } +} + +.top-nav-wrapper { + background-color: #ececec; + position: fixed; + top: 0px; + left: 0px; + padding: 10px 10px 0 10px; + z-index: 999; + width: 300px; +} + +.top-nav-wrapper ul { + margin: 0; +} + +.top-nav-wrapper ul li { + display: inline-block; + padding: 0 10px; + vertical-align: top; +} + +.top-nav-wrapper ul li.active { + border-bottom: 2px solid rgba(28, 160, 224, 1); +} + +.search-wrapper { + display: inline-block; + position: relative; +} + +.search-wrapper svg { + position: absolute; + left: 0px; +} + +input.search-input { + background: transparent; + box-shadow: 0; + border: 0; + border-bottom: 1px solid #c7c7c7; + padding: 7px 15px 12px 35px; + margin: 0 auto; +} + + +/* Smooth outline with box-shadow: */ + +input.search-input:focus { + border-bottom: 2px solid rgba(28, 160, 224, 1); + outline: none; +} + + +/* Hightlight JS Paradiso Light Theme */ + +.hljs-comment, .hljs-quote { + color: #776e71 +} + +.hljs-variable, .hljs-template-variable, .hljs-tag, .hljs-name, .hljs-selector-id, .hljs-selector-class, .hljs-regexp, .hljs-link, .hljs-meta { + color: #ef6155 +} + +.hljs-number, .hljs-built_in, .hljs-builtin-name, .hljs-literal, .hljs-type, .hljs-params, .hljs-deletion { + color: #f99b15 +} + +.hljs-title, .hljs-section, .hljs-attribute { + color: #fec418 +} + +.hljs-string, .hljs-symbol, .hljs-bullet, .hljs-addition { + color: #48b685 +} + +.hljs-keyword, .hljs-selector-tag { + color: #815ba4 +} + +.hljs { + display: block; + overflow-x: auto; + background: #e7e9db; + color: #4f424c; + padding: 0.5em +} + +.hljs-emphasis { + font-style: italic +} + +.hljs-strong { + font-weight: bold +} + +.link-icon { + opacity: 0; + position: absolute; + margin-left: -25px; + padding-right: 5px; + padding-top: 2px; +} + +.example-container .link-icon { + margin-top: -6px; +} + +.example-container:hover .link-icon, +.name-container:hover .link-icon { + opacity: .5; +} + +.name-container { + display: flex; + padding-top: 1em; +} diff --git a/docs/styles/prettify-jsdoc.css b/docs/styles/prettify-jsdoc.css new file mode 100644 index 000000000..834a866d4 --- /dev/null +++ b/docs/styles/prettify-jsdoc.css @@ -0,0 +1,111 @@ +/* JSDoc prettify.js theme */ + +/* plain text */ +.pln { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* string content */ +.str { + color: hsl(104, 100%, 24%); + font-weight: normal; + font-style: normal; +} + +/* a keyword */ +.kwd { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a comment */ +.com { + font-weight: normal; + font-style: italic; +} + +/* a type name */ +.typ { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* a literal value */ +.lit { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* punctuation */ +.pun { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* lisp open bracket */ +.opn { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* lisp close bracket */ +.clo { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a markup tag name */ +.tag { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a markup attribute name */ +.atn { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a markup attribute value */ +.atv { + color: #006400; + font-weight: normal; + font-style: normal; +} + +/* a declaration */ +.dec { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* a variable name */ +.var { + color: #000000; + font-weight: normal; + font-style: normal; +} + +/* a function name */ +.fun { + color: #000000; + font-weight: bold; + font-style: normal; +} + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; +} diff --git a/docs/styles/prettify-tomorrow.css b/docs/styles/prettify-tomorrow.css new file mode 100644 index 000000000..eaf125103 --- /dev/null +++ b/docs/styles/prettify-tomorrow.css @@ -0,0 +1,138 @@ +/* Tomorrow Theme */ +/* Original theme - https://github.com/chriskempson/tomorrow-theme */ +/* Pretty printing styles. Used with prettify.js. */ +/* SPAN elements with the classes below are added by prettyprint. */ +/* plain text */ +.pln { + color: #4d4d4c; } + +@media screen { + /* string content */ + .str { + color: hsl(104, 100%, 24%); } + + /* a keyword */ + .kwd { + color: hsl(240, 100%, 50%); } + + /* a comment */ + .com { + color: hsl(0, 0%, 60%); } + + /* a type name */ + .typ { + color: hsl(240, 100%, 32%); } + + /* a literal value */ + .lit { + color: hsl(240, 100%, 40%); } + + /* punctuation */ + .pun { + color: #000000; } + + /* lisp open bracket */ + .opn { + color: #000000; } + + /* lisp close bracket */ + .clo { + color: #000000; } + + /* a markup tag name */ + .tag { + color: #c82829; } + + /* a markup attribute name */ + .atn { + color: #f5871f; } + + /* a markup attribute value */ + .atv { + color: #3e999f; } + + /* a declaration */ + .dec { + color: #f5871f; } + + /* a variable name */ + .var { + color: #c82829; } + + /* a function name */ + .fun { + color: #4271ae; } } +/* Use higher contrast and text-weight for printable form. */ +@media print, projection { + .str { + color: #060; } + + .kwd { + color: #006; + font-weight: bold; } + + .com { + color: #600; + font-style: italic; } + + .typ { + color: #404; + font-weight: bold; } + + .lit { + color: #044; } + + .pun, .opn, .clo { + color: #440; } + + .tag { + color: #006; + font-weight: bold; } + + .atn { + color: #404; } + + .atv { + color: #060; } } +/* Style */ +/* +pre.prettyprint { + background: white; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 12px; + line-height: 1.5; + border: 1px solid #ccc; + padding: 10px; } +*/ + +/* Get LI elements to show when they are in the main article */ +article ul li { + list-style-type: circle; + margin-left: 25px; +} + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; } + +/* IE indents via margin-left */ +li.L0, +li.L1, +li.L2, +li.L3, +li.L4, +li.L5, +li.L6, +li.L7, +li.L8, +li.L9 { + /* */ } + +/* Alternate shading for lines */ +li.L1, +li.L3, +li.L5, +li.L7, +li.L9 { + /* */ } diff --git a/docs/tokens.js.html b/docs/tokens.js.html new file mode 100644 index 000000000..2d69330b2 --- /dev/null +++ b/docs/tokens.js.html @@ -0,0 +1,425 @@ + + + + + + + + + + + tokens.js - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ tokens.js +

+ + + + + +
+
+
/**
+ * Copyright (C) 2018 Glayzzle (BSD3 License)
+ * @authors https://github.com/glayzzle/php-parser/graphs/contributors
+ * @url http://glayzzle.com
+ */
+"use strict";
+
+/**
+ * PHP AST Tokens
+ * @type {Object}
+ */
+module.exports = {
+  values: {
+    101: "T_HALT_COMPILER",
+    102: "T_USE",
+    103: "T_ENCAPSED_AND_WHITESPACE",
+    104: "T_OBJECT_OPERATOR",
+    105: "T_STRING",
+    106: "T_DOLLAR_OPEN_CURLY_BRACES",
+    107: "T_STRING_VARNAME",
+    108: "T_CURLY_OPEN",
+    109: "T_NUM_STRING",
+    110: "T_ISSET",
+    111: "T_EMPTY",
+    112: "T_INCLUDE",
+    113: "T_INCLUDE_ONCE",
+    114: "T_EVAL",
+    115: "T_REQUIRE",
+    116: "T_REQUIRE_ONCE",
+    117: "T_NAMESPACE",
+    118: "T_NS_SEPARATOR",
+    119: "T_AS",
+    120: "T_IF",
+    121: "T_ENDIF",
+    122: "T_WHILE",
+    123: "T_DO",
+    124: "T_FOR",
+    125: "T_SWITCH",
+    126: "T_BREAK",
+    127: "T_CONTINUE",
+    128: "T_RETURN",
+    129: "T_GLOBAL",
+    130: "T_STATIC",
+    131: "T_ECHO",
+    132: "T_INLINE_HTML",
+    133: "T_UNSET",
+    134: "T_FOREACH",
+    135: "T_DECLARE",
+    136: "T_TRY",
+    137: "T_THROW",
+    138: "T_GOTO",
+    139: "T_FINALLY",
+    140: "T_CATCH",
+    141: "T_ENDDECLARE",
+    142: "T_LIST",
+    143: "T_CLONE",
+    144: "T_PLUS_EQUAL",
+    145: "T_MINUS_EQUAL",
+    146: "T_MUL_EQUAL",
+    147: "T_DIV_EQUAL",
+    148: "T_CONCAT_EQUAL",
+    149: "T_MOD_EQUAL",
+    150: "T_AND_EQUAL",
+    151: "T_OR_EQUAL",
+    152: "T_XOR_EQUAL",
+    153: "T_SL_EQUAL",
+    154: "T_SR_EQUAL",
+    155: "T_INC",
+    156: "T_DEC",
+    157: "T_BOOLEAN_OR",
+    158: "T_BOOLEAN_AND",
+    159: "T_LOGICAL_OR",
+    160: "T_LOGICAL_AND",
+    161: "T_LOGICAL_XOR",
+    162: "T_SL",
+    163: "T_SR",
+    164: "T_IS_IDENTICAL",
+    165: "T_IS_NOT_IDENTICAL",
+    166: "T_IS_EQUAL",
+    167: "T_IS_NOT_EQUAL",
+    168: "T_IS_SMALLER_OR_EQUAL",
+    169: "T_IS_GREATER_OR_EQUAL",
+    170: "T_INSTANCEOF",
+    171: "T_INT_CAST",
+    172: "T_DOUBLE_CAST",
+    173: "T_STRING_CAST",
+    174: "T_ARRAY_CAST",
+    175: "T_OBJECT_CAST",
+    176: "T_BOOL_CAST",
+    177: "T_UNSET_CAST",
+    178: "T_EXIT",
+    179: "T_PRINT",
+    180: "T_YIELD",
+    181: "T_YIELD_FROM",
+    182: "T_FUNCTION",
+    183: "T_DOUBLE_ARROW",
+    184: "T_DOUBLE_COLON",
+    185: "T_ARRAY",
+    186: "T_CALLABLE",
+    187: "T_CLASS",
+    188: "T_ABSTRACT",
+    189: "T_TRAIT",
+    190: "T_FINAL",
+    191: "T_EXTENDS",
+    192: "T_INTERFACE",
+    193: "T_IMPLEMENTS",
+    194: "T_VAR",
+    195: "T_PUBLIC",
+    196: "T_PROTECTED",
+    197: "T_PRIVATE",
+    198: "T_CONST",
+    199: "T_NEW",
+    200: "T_INSTEADOF",
+    201: "T_ELSEIF",
+    202: "T_ELSE",
+    203: "T_ENDSWITCH",
+    204: "T_CASE",
+    205: "T_DEFAULT",
+    206: "T_ENDFOR",
+    207: "T_ENDFOREACH",
+    208: "T_ENDWHILE",
+    209: "T_CONSTANT_ENCAPSED_STRING",
+    210: "T_LNUMBER",
+    211: "T_DNUMBER",
+    212: "T_LINE",
+    213: "T_FILE",
+    214: "T_DIR",
+    215: "T_TRAIT_C",
+    216: "T_METHOD_C",
+    217: "T_FUNC_C",
+    218: "T_NS_C",
+    219: "T_START_HEREDOC",
+    220: "T_END_HEREDOC",
+    221: "T_CLASS_C",
+    222: "T_VARIABLE",
+    223: "T_OPEN_TAG",
+    224: "T_OPEN_TAG_WITH_ECHO",
+    225: "T_CLOSE_TAG",
+    226: "T_WHITESPACE",
+    227: "T_COMMENT",
+    228: "T_DOC_COMMENT",
+    229: "T_ELLIPSIS",
+    230: "T_COALESCE",
+    231: "T_POW",
+    232: "T_POW_EQUAL",
+    233: "T_SPACESHIP"
+  },
+  names: {
+    T_HALT_COMPILER: 101,
+    T_USE: 102,
+    T_ENCAPSED_AND_WHITESPACE: 103,
+    T_OBJECT_OPERATOR: 104,
+    T_STRING: 105,
+    T_DOLLAR_OPEN_CURLY_BRACES: 106,
+    T_STRING_VARNAME: 107,
+    T_CURLY_OPEN: 108,
+    T_NUM_STRING: 109,
+    T_ISSET: 110,
+    T_EMPTY: 111,
+    T_INCLUDE: 112,
+    T_INCLUDE_ONCE: 113,
+    T_EVAL: 114,
+    T_REQUIRE: 115,
+    T_REQUIRE_ONCE: 116,
+    T_NAMESPACE: 117,
+    T_NS_SEPARATOR: 118,
+    T_AS: 119,
+    T_IF: 120,
+    T_ENDIF: 121,
+    T_WHILE: 122,
+    T_DO: 123,
+    T_FOR: 124,
+    T_SWITCH: 125,
+    T_BREAK: 126,
+    T_CONTINUE: 127,
+    T_RETURN: 128,
+    T_GLOBAL: 129,
+    T_STATIC: 130,
+    T_ECHO: 131,
+    T_INLINE_HTML: 132,
+    T_UNSET: 133,
+    T_FOREACH: 134,
+    T_DECLARE: 135,
+    T_TRY: 136,
+    T_THROW: 137,
+    T_GOTO: 138,
+    T_FINALLY: 139,
+    T_CATCH: 140,
+    T_ENDDECLARE: 141,
+    T_LIST: 142,
+    T_CLONE: 143,
+    T_PLUS_EQUAL: 144,
+    T_MINUS_EQUAL: 145,
+    T_MUL_EQUAL: 146,
+    T_DIV_EQUAL: 147,
+    T_CONCAT_EQUAL: 148,
+    T_MOD_EQUAL: 149,
+    T_AND_EQUAL: 150,
+    T_OR_EQUAL: 151,
+    T_XOR_EQUAL: 152,
+    T_SL_EQUAL: 153,
+    T_SR_EQUAL: 154,
+    T_INC: 155,
+    T_DEC: 156,
+    T_BOOLEAN_OR: 157,
+    T_BOOLEAN_AND: 158,
+    T_LOGICAL_OR: 159,
+    T_LOGICAL_AND: 160,
+    T_LOGICAL_XOR: 161,
+    T_SL: 162,
+    T_SR: 163,
+    T_IS_IDENTICAL: 164,
+    T_IS_NOT_IDENTICAL: 165,
+    T_IS_EQUAL: 166,
+    T_IS_NOT_EQUAL: 167,
+    T_IS_SMALLER_OR_EQUAL: 168,
+    T_IS_GREATER_OR_EQUAL: 169,
+    T_INSTANCEOF: 170,
+    T_INT_CAST: 171,
+    T_DOUBLE_CAST: 172,
+    T_STRING_CAST: 173,
+    T_ARRAY_CAST: 174,
+    T_OBJECT_CAST: 175,
+    T_BOOL_CAST: 176,
+    T_UNSET_CAST: 177,
+    T_EXIT: 178,
+    T_PRINT: 179,
+    T_YIELD: 180,
+    T_YIELD_FROM: 181,
+    T_FUNCTION: 182,
+    T_DOUBLE_ARROW: 183,
+    T_DOUBLE_COLON: 184,
+    T_ARRAY: 185,
+    T_CALLABLE: 186,
+    T_CLASS: 187,
+    T_ABSTRACT: 188,
+    T_TRAIT: 189,
+    T_FINAL: 190,
+    T_EXTENDS: 191,
+    T_INTERFACE: 192,
+    T_IMPLEMENTS: 193,
+    T_VAR: 194,
+    T_PUBLIC: 195,
+    T_PROTECTED: 196,
+    T_PRIVATE: 197,
+    T_CONST: 198,
+    T_NEW: 199,
+    T_INSTEADOF: 200,
+    T_ELSEIF: 201,
+    T_ELSE: 202,
+    T_ENDSWITCH: 203,
+    T_CASE: 204,
+    T_DEFAULT: 205,
+    T_ENDFOR: 206,
+    T_ENDFOREACH: 207,
+    T_ENDWHILE: 208,
+    T_CONSTANT_ENCAPSED_STRING: 209,
+    T_LNUMBER: 210,
+    T_DNUMBER: 211,
+    T_LINE: 212,
+    T_FILE: 213,
+    T_DIR: 214,
+    T_TRAIT_C: 215,
+    T_METHOD_C: 216,
+    T_FUNC_C: 217,
+    T_NS_C: 218,
+    T_START_HEREDOC: 219,
+    T_END_HEREDOC: 220,
+    T_CLASS_C: 221,
+    T_VARIABLE: 222,
+    T_OPEN_TAG: 223,
+    T_OPEN_TAG_WITH_ECHO: 224,
+    T_CLOSE_TAG: 225,
+    T_WHITESPACE: 226,
+    T_COMMENT: 227,
+    T_DOC_COMMENT: 228,
+    T_ELLIPSIS: 229,
+    T_COALESCE: 230,
+    T_POW: 231,
+    T_POW_EQUAL: 232,
+    T_SPACESHIP: 233
+  }
+};
+
+
+
+ + + + +
+ +
+ + + + + + + + + + + + diff --git a/docs/tutorial-AST_.html b/docs/tutorial-AST_.html new file mode 100644 index 000000000..c18a13c77 --- /dev/null +++ b/docs/tutorial-AST_.html @@ -0,0 +1,303 @@ + + + + + + + + + Tutorial: AST - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Tutorial: AST +

+ + +
+
+ + +

+ AST +

+
+ +
+

Abstract Syntax Tree

+

You can see the AST as a DOM document, the source code of the program beeing +the graphical text output, and the DOM beeing a representation of it.

+

The main node is the program node, and it's structured like this :

+
  {
+    "kind": "program",
+    "children": [
+      // array of nodes
+    ]
+  }
+
+

Nodes

+

Every node has a common structure enabling you to scan them and act accordingly.

+

NOTE : This structure depends also on what options you enable.

+
  {
+    "kind": "node name",
+    "loc": {
+      ""
+    },
+    // the location node
+    "loc": {
+      "source": "original source code of the node",
+      "start": {
+        "line": 1, // 1 based
+        "column": 0, // 0 based
+        "offset": 0 // offset from the source code
+      },
+      "end": {
+        // same structure as start
+      }
+    },
+    "leadingComments": [
+      // array of comments nodes
+    ]
+  }
+
+

Nodes hierarchy

+ +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/tutorial-Engine_.html b/docs/tutorial-Engine_.html new file mode 100644 index 000000000..f99fb1f8b --- /dev/null +++ b/docs/tutorial-Engine_.html @@ -0,0 +1,217 @@ + + + + + + + + + Tutorial: Engine - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Tutorial: Engine +

+ + +
+
+ + +

+ Engine +

+
+ +
+

Initialise a new parser instance with the specified options

+

Usage :

+
var parser = require('php-parser');
+var instance = new parser({
+  parser: {
+    extractDoc: true,
+    suppressErrors: true,
+    php7: true
+  },
+  ast: {
+    withPositions: true
+  },
+  lexer: {
+    short_tags: true,
+    asp_tags: true
+  }
+});
+
+var evalAST = instance.parseEval('some php code');
+var codeAST = instance.parseCode('<?php some php code', 'foo.php');
+var tokens = instance.tokenGetAll('<?php some php code');
+
+

Type: Engine

+

Parameters

+
    +
  • options Object List of options
  • +
+

Properties

+
    +
  • lexer Lexer
  • +
  • parser Parser
  • +
  • ast AST
  • +
  • tokens Object
  • +
+

parseEval

+

Parse an evaluating mode string (no need to open php tags)

+

Parameters

+ +

Returns Program

+

parseCode

+

Function that parse a php code with open/close tags

+

Sample code :

+
<?php $x = 1;
+
+

Usage :

+
var parser = require('php-parser');
+var phpParser = new parser({
+  // some options
+});
+var ast = phpParser.parseCode('...php code...', 'foo.php');
+
+

Parameters

+
    +
  • buffer String The code to be parsed
  • +
  • filename String Filename
  • +
+

Returns Program

+

tokenGetAll

+

Extract tokens from the specified buffer.

+
+

Note that the output tokens are STRICLY similar to PHP function token_get_all

+
+

Parameters

+ +

Returns Array<String> Each item can be a string or an array with following informations [token_name, text, line_number]

+

getStringBuffer

+

Check if the inpyt is a buffer or a string

+

Parameters

+
    +
  • buffer (Buffer | String) Input value that can be either a buffer or a string
  • +
+

Returns String Returns the string from input

+
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/tutorial-Options.html b/docs/tutorial-Options.html new file mode 100644 index 000000000..1c4642b69 --- /dev/null +++ b/docs/tutorial-Options.html @@ -0,0 +1,179 @@ + + + + + + + + + Tutorial: Options - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Tutorial: Options +

+ + +
+
+ + +

+ Options +

+
+ +
+

Options

+

When you call the parser you can pass options as following :

+
var reader = require('php-parser');
+reader.parseCode('<?php echo true;', {
+  parser: {
+    debug: false, 
+    locations: false,
+    extractDoc: false,
+    suppressErrors: false
+  },
+  ast: {
+    withPositions: true,
+    withSource: true
+  },
+  lexer: {
+    all_tokens: false,
+    comment_tokens: false,
+    mode_eval: false,
+    asp_tags: false,
+    short_tags: false
+  }
+});
+
+

Parser

+
    +
  • debug : enables debug output, useful for handling parsing errors when extending the library.
  • +
  • locations : attach location nodes to AST - see more details
  • +
  • extractDoc : extracting comments blocks - see more details
  • +
  • suppressErrors: graceful parsing mode, when an error is raised it's ignored see more details
  • +
+

Lexer

+
    +
  • all_tokens : extract all tokens (same output as token_get_all function in PHP)
  • +
  • comment_tokens: extract also comments tokens (used when all_tokens is false)
  • +
  • mode_eval: ignoring open or close tags, the input is directly a PHP script
  • +
  • asp_tags: handles ASP like tags <% and %>
  • +
  • short_tags : handle short opening tag <?
  • +
+
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/tutorial-Parser_.html b/docs/tutorial-Parser_.html new file mode 100644 index 000000000..c0133e942 --- /dev/null +++ b/docs/tutorial-Parser_.html @@ -0,0 +1,572 @@ + + + + + + + + + Tutorial: Parser - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ Tutorial: Parser +

+ + +
+
+ + +

+ Parser +

+
+ +
+

The PHP Parser class that build the AST tree from the lexer

+

Type: Parser

+

Parameters

+
    +
  • lexer
  • +
  • ast
  • +
+

Properties

+
    +
  • lexer Lexer current lexer instance
  • +
  • ast AST the AST factory instance
  • +
  • token (Integer | String) current token
  • +
  • extractDoc Boolean should extract documentation as AST node
  • +
  • extractTokens Boolean should extract each token
  • +
  • suppressErrors Boolean should ignore parsing errors and continue
  • +
  • debug Boolean should output debug informations
  • +
+

getTokenName

+

helper : gets a token name

+

Parameters

+
    +
  • token
  • +
+

parse

+

main entry point : converts a source code to AST

+

Parameters

+
    +
  • code
  • +
  • filename
  • +
+

raiseError

+

Raise an error

+

Parameters

+
    +
  • message
  • +
  • msgExpect
  • +
  • expect
  • +
  • token
  • +
+

error

+

handling errors

+

Parameters

+
    +
  • expect
  • +
+

node

+

Creates a new AST node

+

Parameters

+
    +
  • name
  • +
+

expectEndOfStatement

+

expects an end of statement or end of file

+

Returns boolean

+

expect

+

Force the parser to check the current token.

+

If the current token does not match to expected token, +the an error will be raised.

+

If the suppressError mode is activated, then the error will +be added to the program error stack and this function will return false.

+

Parameters

+ +
    +
  • Throws any Error
  • +
+

Returns boolean

+

text

+

Returns the current token contents

+

Returns String

+

next

+

consume the next token *

+

lex

+

Eating a token

+

is

+

Check if token is of specified type

+

Parameters

+
    +
  • type
  • +
+

ignoreStack

+

outputs some debug information on current token *

+

read_array

+

Parse an array

+
array ::= T_ARRAY '(' array_pair_list ')' |
+  '[' array_pair_list ']'
+
+

read_array_pair_list

+

Reads an array entry item

+
array_pair_list ::= '&' w_variable |
+ (
+   expr (
+     T_DOUBLE_ARROW (
+       expr | '&' w_variable
+     )
+   )?
+ )
+
+

read_dim_offset

+
 dim_offset ::= expr?
+
+

read_class

+

reading a class

+
class ::= class_scope? T_CLASS T_STRING (T_EXTENDS NAMESPACE_NAME)? (T_IMPLEMENTS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' CLASS_BODY '}'
+
+

read_class_scope

+

Read the class visibility

+
  class_scope ::= (T_FINAL | T_ABSTRACT)?
+
+

read_class_body

+

Reads a class body

+
  class_body ::= (member_flags? (T_VAR | T_STRING | T_FUNCTION))*
+
+

read_variable_list

+

Reads variable list

+
 variable_list ::= (variable_declaration ',')* variable_declaration
+
+

read_constant_list

+

Reads constant list

+
 constant_list ::= T_CONST (constant_declaration ',')* constant_declaration
+
+

read_member_flags

+

Read member flags

+

Returns any array +1st index : 0 => public, 1 => protected, 2 => private +2nd index : 0 => instance member, 1 => static member +3rd index : 0 => normal, 1 => abstract member, 2 => final member

+

read_interface

+

reading an interface

+
interface ::= T_INTERFACE T_STRING (T_EXTENDS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' INTERFACE_BODY '}'
+
+

read_interface_body

+

Reads an interface body

+
  interface_body ::= (member_flags? (T_CONST | T_FUNCTION))*
+
+

read_trait

+

reading a trait

+
trait ::= T_TRAIT T_STRING (T_EXTENDS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' FUNCTION* '}'
+
+

read_trait_use_statement

+

reading a use statement

+
trait_use_statement ::= namespace_name (',' namespace_name)* ('{' trait_use_alias '}')?
+
+

read_trait_use_alias

+

Reading trait alias

+
trait_use_alias ::= namespace_name ( T_DOUBLE_COLON T_STRING )? (T_INSTEADOF namespace_name) | (T_AS member_flags? T_STRING)
+
+

name list : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L303 +trait adaptation : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L742

+

read_variable_declaration

+

Reads a variable declaration

+
 variable_declaration ::= T_VARIABLE '=' scalar
+
+

read_constant_declaration

+

Reads a constant declaration

+
 constant_declaration ::= (T_STRING | IDENTIFIER) '=' expr
+
+

Returns Constant :link:

+

read_comment

+

Comments with // or # or / _ ... _ /

+

read_doc_comment

+

Comments with / *_ ... _ /

+

read_expr_item

+
Reads an expression
+ expr ::= @todo
+
+

read_new_expr

+
   new_expr ::= T_NEW (namespace_name function_argument_list) | (T_CLASS ... class declaration)
+
+

https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L850

+

read_class_name_reference

+

Reads a class name

+
class_name_reference ::= namespace_name | variable
+
+

read_assignment_list

+
  assignment_list ::= assignment_list_element (',' assignment_list_element?)*
+
+

read_assignment_list_element

+
 assignment_list_element ::= expr | expr T_DOUBLE_ARROW expr
+
+

is_reference

+

checks if current token is a reference keyword

+

is_variadic

+

checks if current token is a variadic keyword

+

read_function

+

reading a function

+
function ::= function_declaration code_block
+
+

read_function_declaration

+

reads a function declaration (without his body)

+
function_declaration ::= T_FUNCTION '&'?  T_STRING '(' parameter_list ')'
+
+

read_lexical_var

+
lexical_var ::= '&'? T_VARIABLE
+
+

read_parameter_list

+

reads a list of parameters

+
 parameter_list ::= (parameter ',')* parameter?
+
+

read_parameter

+
 parameter ::= type? '&'? T_ELLIPSIS? T_VARIABLE ('=' expr)?
+
+

read_function_argument_list

+

Reads a list of arguments

+
 function_argument_list ::= '(' (argument_list (',' argument_list)*)? ')'
+
+

read_argument_list

+
   argument_list ::= T_ELLIPSIS? expr
+
+

read_type

+

read type hinting

+
 type ::= T_ARRAY | T_CALLABLE | namespace_name
+
+

read_if

+

Reads an IF statement

+
 if ::= T_IF '(' expr ')' ':' ...
+
+

read_if_expr

+

reads an if expression : '(' expr ')'

+

read_elseif_short

+

reads an elseif (expr): statements

+

read_else_short

+

read_while

+

Reads a while statement

+
while ::= T_WHILE (statement | ':' inner_statement_list T_ENDWHILE ';')
+
+

Returns While

+

read_do

+

Reads a do / while loop

+
do ::= T_DO statement T_WHILE '(' expr ')' ';'
+
+

Returns Do

+

read_for

+

Read a for incremental loop

+
for ::= T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement
+for_statement ::= statement | ':' inner_statement_list T_ENDFOR ';'
+for_exprs ::= expr? (',' expr)*
+
+

Returns For

+

read_foreach

+

Reads a foreach loop

+
foreach ::= '(' expr T_AS foreach_variable (T_DOUBLE_ARROW foreach_variable)? ')' statement
+
+

Returns Foreach

+

read_foreach_variable

+

Reads a foreach variable statement

+
foreach_variable = variable |
+ T_LIST '(' assignment_list ')' |
+ '[' array_pair_list ']'
+
+

Returns Expression

+

read_start

+
start ::= (namespace | top_statement)*
+
+

read_namespace

+

Reads a namespace declaration block

+
namespace ::= T_NAMESPACE namespace_name? '{'
+   top_statements
+'}'
+| T_NAMESPACE namespace_name ';' top_statements
+
+

Returns Namespace

+

read_namespace_name

+

Reads a namespace name

+
 namespace_name ::= T_NS_SEPARATOR? (T_STRING T_NS_SEPARATOR)* T_STRING
+
+

Returns Identifier

+

read_use_statement

+

Reads a use statement

+
use_statement ::= T_USE
+  use_type? use_declarations |
+  use_type use_statement '{' use_declarations '}' |
+  use_statement '{' use_declarations(=>typed) '}'
+';'
+
+

Returns UseGroup

+

read_use_declaration

+

Reads a use declaration

+
use_declaration ::= use_type? namespace_name use_alias
+
+

Returns UseItem

+

read_use_declarations

+

Reads a list of use declarations

+
use_declarations ::= use_declaration (',' use_declaration)*
+
+

Returns Array<UseItem>

+

read_use_alias

+

Reads a use statement

+
use_alias ::= (T_AS T_STRING)?
+
+

Returns (String | null)

+

read_use_type

+

Reads the namespace type declaration

+
use_type ::= (T_FUNCTION | T_CONST)?
+
+

Returns (String | null) Possible values : function, const

+

resolve_special_chars

+

Unescape special chars

+

read_scalar

+
 scalar ::= T_MAGIC_CONST
+      | T_LNUMBER | T_DNUMBER
+      | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE? T_END_HEREDOC
+      | '"' encaps_list '"'
+      | T_START_HEREDOC encaps_list T_END_HEREDOC
+      | namespace_name (T_DOUBLE_COLON T_STRING)?
+
+

read_dereferencable

+

Handles the dereferencing

+

read_encapsed_string_item

+

Reads and extracts an encapsed item

+
encapsed_string_item ::= T_ENCAPSED_AND_WHITESPACE
+ | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
+ | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}'
+ | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
+ | T_CURLY_OPEN variable '}'
+ | variable
+ | variable '[' expr ']'
+ | variable T_OBJECT_OPERATOR T_STRING
+
+

Returns (String | Variable | Expr | Lookup)

+

read_encapsed_string

+

Reads an encapsed string

+

get_magic_constant

+

Constant token

+

read_top_statements

+

reading a list of top statements (helper for top_statement*)

+
 top_statements ::= top_statement*
+
+

read_top_statement

+

reading a top statement

+
 top_statement ::=
+      namespace | function | class
+      | interface | trait
+      | use_statements | const_list
+      | statement
+
+

read_inner_statements

+

reads a list of simple inner statements (helper for inner_statement*)

+
 inner_statements ::= inner_statement*
+
+

read_const_list

+

Reads a list of constants declaration

+
  const_list ::= T_CONST T_STRING '=' expr (',' T_STRING '=' expr)* ';'
+
+

read_declare_list

+

Reads a list of constants declaration

+
  declare_list ::= T_STRING '=' expr (',' T_STRING '=' expr)*
+
+

read_inner_statement

+

reads a simple inner statement

+
 inner_statement ::= '{' inner_statements '}' | token
+
+

read_statement

+

Reads statements

+

read_code_block

+
 code_block ::= '{' (inner_statements | top_statements) '}'
+
+

read_switch

+

Reads a switch statement

+
 switch ::= T_SWITCH '(' expr ')' switch_case_list
+
+

Returns Switch

+

read_switch_case_list

+
 switch_case_list ::= '{' ';'? case_list* '}' | ':' ';'? case_list* T_ENDSWITCH ';'
+
+

read_case_list

+
  case_list ::= ((T_CASE expr) | T_DEFAULT) (':' | ';') inner_statement*
+
+

read_try

+
 try ::= T_TRY '{' inner_statement* '}'
+         (
+             T_CATCH '(' namespace_name variable ')' '{'  inner_statement* '}'
+         )*
+         (T_FINALLY '{' inner_statement* '}')?
+
+

Returns Try

+

read_short_form

+

Reads a short form of tokens

+

Parameters

+
    +
  • token Number The ending token
  • +
+

Returns Block

+

read_list

+

Helper : reads a list of tokens / sample : T_STRING ',' T_STRING ...

+
list ::= separator? ( item separator )* item
+
+

read_name_list

+

Reads a list of names separated by a comma

+
name_list ::= namespace (',' namespace)*
+
+

Sample code :

+
<?php class foo extends bar, baz { }
+
+

Returns Array<Identifier>

+

read_variable_declarations

+

Reads a list of variables declarations

+
variable_declaration ::= T_VARIABLE ('=' expr)?*
+variable_declarations ::= variable_declaration (',' variable_declaration)*
+
+

Sample code :

+
<?php class foo extends bar, baz { }
+
+

Returns (Array<Variable> | Array<Assign>) Returns an array composed by a list of variables, or +assign values

+

read_variable

+

Reads a variable

+
  variable ::= &? ...complex @todo
+
+

Some samples of parsed code :

+
 &$var                      // simple var
+ $var                      // simple var
+ classname::CONST_NAME     // dynamic class name with const retrieval
+ foo()                     // function call
+ $var->func()->property    // chained calls
+
+

read_encaps_var_offset

+

https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L1231

+

read_reference_variable

+
 reference_variable ::=  simple_variable ('[' OFFSET ']')* | '{' EXPR '}'
+
+ + $foo[123]; // foo is an array ==> gets its entry + $foo{1}; // foo is a string ==> get the 2nd char offset + ${'foo'}[123]; // get the dynamic var $foo + $foo[123]{1}; // gets the 2nd char from the 123 array entry + +

read_simple_variable

+
 simple_variable ::= T_VARIABLE | '$' '{' expr '}' | '$' simple_variable
+
+
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/docs/variadic.html b/docs/variadic.html new file mode 100644 index 000000000..d9f68a141 --- /dev/null +++ b/docs/variadic.html @@ -0,0 +1,762 @@ + + + + + + + + + variadic - Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + +
+ +

+ variadic +

+ + + + +
+
+ +

+ + variadic + +

+ + + +
+ +
+
+ + + + + + + + + + + + +

+ new variadic() +

+
+ + + + + +
+

Introduce a list of items into the arguments of the call

+
+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
what + + + + Array + + + | + + + Expression + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + +
See:
+
+ +
+ + + +
+ + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + +

+ destroy() +

+
+ + + + + +
+

Destroying an unused node

+
+ + + + + + + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ includeToken(parser) +

+
+ + + + + +
+

Includes current token position of the parser

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
parser + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ setTrailingComments(docs) +

+
+ + + + + +
+

Attach comments to current node

+
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
docs + + + + * + + + + + + + + + +
+ + + + + +
+ + + + + + +
Inherited From:
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ +
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..898d304ee --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,38 @@ +import js from "@eslint/js"; +import jest from "eslint-plugin-jest"; +import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; +import globals from "globals"; + +export default [ + { + ignores: ["dist", "docs", "example", "tutorials"], + }, + js.configs.recommended, + { + files: ["test/**"], + ...jest.configs["flat/recommended"], + rules: { + ...jest.configs["flat/recommended"].rules, + "no-console": "off", + }, + languageOptions: { + globals: jest.environments.globals.globals, + }, + }, + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + }, + sourceType: "commonjs", + }, + + rules: { + "prefer-const": "error", + "no-var": "error", + curly: ["error", "multi-line"], + }, + }, + eslintPluginPrettierRecommended, +]; diff --git a/gruntfile.js b/gruntfile.js deleted file mode 100644 index 25faabb80..000000000 --- a/gruntfile.js +++ /dev/null @@ -1,98 +0,0 @@ -module.exports = function(grunt) { - - // Project configuration. - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - browserify: { - options: { - banner: '/*! <%= pkg.name %> - BSD3 License - <%= grunt.template.today("yyyy-mm-dd") %> */\n', - alias: { - 'php-parser': './src/index.js' - } - }, - dist: { - files: { - 'dist/<%= pkg.name %>.js': 'index.js' // ['src/*.js', 'src/**/*.js'] - } - } - }, - documentation: { - ast: { - options: { - destination: "docs/", - format: "md", - version: "<%= pkg.version %>", - name: "<%= pkg.name %>", - filename: "AST.md", - shallow: false - }, - files: [{ - src: ['src/ast.js', 'src/ast'] - }] - }, - parser: { - options: { - destination: "docs/", - format: "md", - version: "<%= pkg.version %>", - name: "<%= pkg.name %>", - filename: "parser.md", - shallow: false - }, - files: [{ - src: ['src/parser.js','src/parser'] - }] - }, - lexer: { - options: { - destination: "docs/", - format: "md", - version: "<%= pkg.version %>", - name: "<%= pkg.name %>", - filename: "lexer.md", - shallow: false - }, - files: [{ - src: ['src/lexer.js', 'src/lexer'] - }] - }, - main: { - options: { - destination: "docs/", - format: "md", - version: "<%= pkg.version %>", - name: "<%= pkg.name %>", - filename: "README.md", - shallow: true - }, - files: [{ - src: ['src/index.js'] - }] - } - }, - uglify: { - options: { - compress: { - keep_fnames: true - }, - sourceMap: true, - mangle: false, - maxLineLen: 1024 - }, - dist: { - src: 'dist/<%= pkg.name %>.js', - dest: 'dist/<%= pkg.name %>.min.js' - } - } - }); - - // Load the plugin - grunt.loadNpmTasks('grunt-browserify'); - grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-documentation'); - - // Default task(s). - grunt.registerTask('default', ['browserify', 'uglify']); - grunt.registerTask('doc', ['documentation']); - -}; diff --git a/index.d.ts b/index.d.ts deleted file mode 100644 index 6d72fb1b6..000000000 --- a/index.d.ts +++ /dev/null @@ -1,364 +0,0 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -declare module "php-parser" { - /** - * Token items - */ - const enum TokenEnum { - T_HALT_COMPILER = 101, - T_USE = 102, - T_ENCAPSED_AND_WHITESPACE = 103, - T_OBJECT_OPERATOR = 104, - T_STRING = 105, - T_DOLLAR_OPEN_CURLY_BRACES = 106, - T_STRING_VARNAME = 107, - T_CURLY_OPEN = 108, - T_NUM_STRING = 109, - T_ISSET = 110, - T_EMPTY = 111, - T_INCLUDE = 112, - T_INCLUDE_ONCE = 113, - T_EVAL = 114, - T_REQUIRE = 115, - T_REQUIRE_ONCE = 116, - T_NAMESPACE = 117, - T_NS_SEPARATOR = 118, - T_AS = 119, - T_IF = 120, - T_ENDIF = 121, - T_WHILE = 122, - T_DO = 123, - T_FOR = 124, - T_SWITCH = 125, - T_BREAK = 126, - T_CONTINUE = 127, - T_RETURN = 128, - T_GLOBAL = 129, - T_STATIC = 130, - T_ECHO = 131, - T_INLINE_HTML = 132, - T_UNSET = 133, - T_FOREACH = 134, - T_DECLARE = 135, - T_TRY = 136, - T_THROW = 137, - T_GOTO = 138, - T_FINALLY = 139, - T_CATCH = 140, - T_ENDDECLARE = 141, - T_LIST = 142, - T_CLONE = 143, - T_PLUS_EQUAL = 144, - T_MINUS_EQUAL = 145, - T_MUL_EQUAL = 146, - T_DIV_EQUAL = 147, - T_CONCAT_EQUAL = 148, - T_MOD_EQUAL = 149, - T_AND_EQUAL = 150, - T_OR_EQUAL = 151, - T_XOR_EQUAL = 152, - T_SL_EQUAL = 153, - T_SR_EQUAL = 154, - T_INC = 155, - T_DEC = 156, - T_BOOLEAN_OR = 157, - T_BOOLEAN_AND = 158, - T_LOGICAL_OR = 159, - T_LOGICAL_AND = 160, - T_LOGICAL_XOR = 161, - T_SL = 162, - T_SR = 163, - T_IS_IDENTICAL = 164, - T_IS_NOT_IDENTICAL = 165, - T_IS_EQUAL = 166, - T_IS_NOT_EQUAL = 167, - T_IS_SMALLER_OR_EQUAL = 168, - T_IS_GREATER_OR_EQUAL = 169, - T_INSTANCEOF = 170, - T_INT_CAST = 171, - T_DOUBLE_CAST = 172, - T_STRING_CAST = 173, - T_ARRAY_CAST = 174, - T_OBJECT_CAST = 175, - T_BOOL_CAST = 176, - T_UNSET_CAST = 177, - T_EXIT = 178, - T_PRINT = 179, - T_YIELD = 180, - T_YIELD_FROM = 181, - T_FUNCTION = 182, - T_DOUBLE_ARROW = 183, - T_DOUBLE_COLON = 184, - T_ARRAY = 185, - T_CALLABLE = 186, - T_CLASS = 187, - T_ABSTRACT = 188, - T_TRAIT = 189, - T_FINAL = 190, - T_EXTENDS = 191, - T_INTERFACE = 192, - T_IMPLEMENTS = 193, - T_VAR = 194, - T_PUBLIC = 195, - T_PROTECTED = 196, - T_PRIVATE = 197, - T_CONST = 198, - T_NEW = 199, - T_INSTEADOF = 200, - T_ELSEIF = 201, - T_ELSE = 202, - T_ENDSWITCH = 203, - T_CASE = 204, - T_DEFAULT = 205, - T_ENDFOR = 206, - T_ENDFOREACH = 207, - T_ENDWHILE = 208, - T_CONSTANT_ENCAPSED_STRING = 209, - T_LNUMBER = 210, - T_DNUMBER = 211, - T_LINE = 212, - T_FILE = 213, - T_DIR = 214, - T_TRAIT_C = 215, - T_METHOD_C = 216, - T_FUNC_C = 217, - T_NS_C = 218, - T_START_HEREDOC = 219, - T_END_HEREDOC = 220, - T_CLASS_C = 221, - T_VARIABLE = 222, - T_OPEN_TAG = 223, - T_OPEN_TAG_WITH_ECHO = 224, - T_CLOSE_TAG = 225, - T_WHITESPACE = 226, - T_COMMENT = 227, - T_DOC_COMMENT = 228, - T_ELLIPSIS = 229, - T_COALESCE = 230, - T_POW = 231, - T_POW_EQUAL = 232, - T_SPACESHIP = 233 - } - - /** - * The tokens dictionnary - */ - interface TokenDefinition { - /** List of token names as texts */ - values: String[], - /** Define tokens */ - names: TokenEnum[] - } - - /** - * The token structure - */ - interface Token extends Array { - // token name - 0: String; - // the token value - 1: TokenEnum; - // the current line - 2: Number - } - - /** - * Each Position object consists of a line number (1-indexed) and a column number (0-indexed): - */ - interface Position { - line: Number; - column: Number; - offset: Number; - } - - /** - * Defines the location of the node (with it's source contents as string) - */ - interface Location { - source: string; - start: Position; - end: Position; - } - - /** - * - */ - interface Node { - kind: String; - loc: Location; - } - - /** - * Error node - */ - interface ParserError extends Node { - message: String; - token: Token; - line: Number; - expected: any; - } - - /** - * A block statement, i.e., a sequence of statements surrounded by braces. - */ - interface Block extends Node { - children: Node[]; - } - - /** - * The main root node - */ - interface Program extends Block { - errors: ParserError[]; - } - - interface Parser { - lexer: Lexer; - ast: AST; - token: TokenEnum; - prev: TokenEnum; - debug: Boolean; - extractDoc: Boolean; - suppressErrors: Boolean; - getTokenName(token:TokenEnum): String; - parse(code: String, filename: String): Program; - raiseError(message: String, msgExpect: String, expect: any, token: TokenEnum): ParserError; - error(expect: String): ParserError; - node(kind:String): Node; - expectEndOfStatement(): Boolean; - showlog(): Parser; - expect(token:TokenEnum): Boolean; - expect(tokens:TokenEnum[]): Boolean; - text(): String; - next(): Parser; - ignoreComments(): Parser; - nextWithComments(): Parser; - is(type: String): Boolean; - // @todo other parsing functions ... - } - - interface KeywordsDictionnary { - [index: string]: TokenEnum - } - - interface yylloc { - first_offset: Number; - first_line: Number; - first_column: Number; - last_line: Number; - last_column: Number; - } - - interface LexerState { - yytext: String; - offset: Number; - yylineno: Number; - yyprevcol: Number; - yylloc: yylloc; - } - - interface Lexer { - debug: Boolean; - all_tokens: Boolean; - comment_tokens: Boolean; - mode_eval: Boolean; - asp_tags: Boolean; - short_tags: Boolean; - keywords: KeywordsDictionnary; - castKeywords: KeywordsDictionnary; - setInput(input:String): Lexer; - input(size:Number): String; - unput(size:Number): Lexer; - tryMatch(match:String): Boolean; - tryMatchCaseless(match:String): Boolean; - ahead(size:Number): String; - consume(size:Number): Lexer; - getState(): LexerState; - setState(state:LexerState): Lexer; - appendToken(value:TokenEnum, ahead:Number): Lexer; - lex(): TokenEnum; - begin(state:String): Lexer; - popState(): String; - next(): TokenEnum; - // @todo other lexer functions ... - } - - - interface AST { - /** - * - */ - withPositions: Boolean; - /** - * Option, if true extracts original source code attached to the node (by default false) - */ - withSource: Boolean; - /** - * Constructor - */ - constructor(withPositions:Boolean, withSource:Boolean): AST; - constructor(withPositions:Boolean): AST; - constructor(): AST; - /** - * Create a position node from specified parser - * including it's lexer current state - */ - position(parser:Parser): Position; - /** - * Prepares an AST node - */ - prepare(kind:String, parser:Parser): Function; - } - - /** - * List of options / extensions - */ - interface Options { - ast?: { - withPositions?: Boolean; - withSource?: Boolean; - }; - lexer?: { - debug?: Boolean; - all_tokens?: Boolean; - comment_tokens?: Boolean; - mode_eval?: Boolean; - asp_tags?: Boolean; - short_tags?: Boolean; - }; - parser?: { - debug?: Boolean; - extractDoc?: Boolean; - suppressErrors?: Boolean; - }; - } - - /** - * Initialise a new parser instance with the specified options - */ - export default class Engine { - // ----- STATIC HELPERS - static create(options?: Options) : Engine; - static parseEval(buffer: String, options: Options) : Program; - static parseEval(buffer: String) : Program; - static parseCode(buffer: String, filename: String, options: Options) : Program; - static parseCode(buffer: String, options: Options) : Program; - static parseCode(buffer: String) : Program; - static tokenGetAll(buffer: String, options: Options) : Token[]; - static tokenGetAll(buffer: String) : Token[]; - // ----- INSTANCE FUNCTIONS - ast: AST; - lexer: Lexer; - parser: Parser; - tokens: TokenDefinition; - constructor(options?: Options); - parseEval(buffer: String) : Program; - parseCode(buffer: String, filename: String) : Program; - parseCode(buffer: String) : Program; - tokenGetAll(buffer: String) : Token[]; - } -} diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 000000000..e8c233467 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,31 @@ +"use strict"; + +const ENABLE_COVERAGE = !!process.env.CI || !!process.env.COVERAGE; + +module.exports = { + collectCoverage: ENABLE_COVERAGE, + coverageDirectory: "coverage/", + coverageThreshold: { + global: { + statements: 96.4, + branches: 90.1, + functions: 99.4, + lines: 96.9, + }, + }, + projects: [ + { + displayName: "test", + testEnvironment: "node", + }, + { + runner: "jest-runner-eslint", + displayName: "lint", + testMatch: ["/**/*.js"], + testPathIgnorePatterns: [ + "/node_modules/", + "/coverage/", + ], + }, + ], +}; diff --git a/package.json b/package.json index 652bbad8a..d2ac370e6 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,28 @@ { "name": "php-parser", - "version": "2.0.6", - "description": "Parse PHP code and returns its AST", + "version": "3.2.3", + "description": "Parse PHP code from JS and returns its AST", "main": "src/index.js", + "browser": "dist/php-parser.js", + "files": [ + "src", + "dist", + "types.d.ts", + "LICENSE" + ], + "types": "types.d.ts", "scripts": { - "test": "node node_modules/mocha/bin/mocha test --stack-size=5000", - "cover": "node --stack-size=5000 node_modules/istanbul/lib/cli.js cover node_modules/mocha/bin/_mocha" + "fix": "eslint . --fix", + "test": "jest", + "prepublishOnly": "yarpm run build", + "prebuild": "yarpm run test", + "build": "webpack --config webpack.config.js", + "-postbuild": "yarpm run build-docs", + "build-docs": "jsdoc -c .jsdoc.json", + "build-types": "jsdoc -t node_modules/tsd-jsdoc/dist -r src -d . && prettier -w types.d.ts", + "publish-docs": "git subtree push --prefix docs origin gh-pages", + "benchmark": "node test/benchmark.js", + "prepare": "husky" }, "repository": { "type": "git", @@ -14,25 +31,57 @@ "bugs": { "url": "https://github.com/glayzzle/php-parser/issues" }, - "homepage": "http://glayzzle.com/php-parser/", + "homepage": "https://glayzzle.com/", "keywords": [ - "php","php5","php7", - "parser","lexer","tokenizer","ast" + "php", + "php5", + "php7", + "php8", + "parser", + "lexer", + "tokenizer", + "ast" ], "author": "Ioan CHIRIAC", + "contributors": [ + { + "name": "Filippo Conti", + "email": "filippo@codekraft.it", + "url": "https://b4dnewz.github.io/" + }, + { + "name": "Christian Zosel", + "email": "christian@zosel.ch", + "url": "https://twitter.com/chrzosel" + } + ], "license": "BSD-3-Clause", - "xo": { - "space": 2, - "envs": ["node", "mocha"] - }, "devDependencies": { - "coveralls": "^2.11.15", - "grunt": "^1.0.1", - "grunt-browserify": "^5.0.0", - "grunt-contrib-uglify": "^2.0.0", - "grunt-documentation": "^1.2.1", - "istanbul": "0.3.x", - "mocha": "^3.2.0", - "should": "^11.2.0" - } + "@babel/core": "^7.26.0", + "@babel/preset-env": "^7.26.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.14.0", + "@types/node": "^22.9.0", + "babel-loader": "^9.2.1", + "benchmark": "^2.1.4", + "coveralls": "^3.0.3", + "eslint": "^9.14.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-jest": "^28.9.0", + "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.12.0", + "husky": "^9.1.6", + "jest": "^29.7.0", + "jest-runner-eslint": "^2.2.1", + "jsdoc": "^3.6.11", + "jsdoc-template": "^1.2.0", + "lodash.template": ">=4.5.0", + "prettier": "^3.3.3", + "tsd-jsdoc": "^2.5.0", + "typescript": "^5.6.3", + "webpack": "5.96.0", + "webpack-cli": "^5.1.4", + "yarpm": "^1.2.0" + }, + "dependencies": {} } diff --git a/src/ast.js b/src/ast.js index 51956169d..d11b556b5 100644 --- a/src/ast.js +++ b/src/ast.js @@ -1,11 +1,12 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://gla*yzzle.com + * @url http://glayzzle.com */ +"use strict"; -var Location = require('./ast/location'); -var Position = require('./ast/position'); +const Location = require("./ast/location"); +const Position = require("./ast/position"); /** * ## Class hierarchy @@ -13,22 +14,49 @@ var Position = require('./ast/position'); * - [Location](#location) * - [Position](#position) * - [Node](#node) + * - [Noop](#noop) + * - [NullKeyword](#nullkeyword) + * - [StaticVariable](#staticvariable) + * - [EncapsedPart](#encapsedpart) + * - [Constant](#constant) * - [Identifier](#identifier) + * - [Reference](#reference) + * - [TypeReference](#typereference) + * - [ParentReference](#parentreference) + * - [StaticReference](#staticreference) + * - [SelfReference](#selfreference) + * - [Name](#name) * - [TraitUse](#traituse) * - [TraitAlias](#traitalias) * - [TraitPrecedence](#traitprecedence) - * - [Entry](#entry) - * - [Case](#case) - * - [Label](#label) - * - [Doc](#doc) + * - [Comment](#comment) + * - [CommentLine](#commentline) + * - [CommentBlock](#commentblock) * - [Error](#error) * - [Expression](#expression) + * - [Entry](#entry) + * - [ArrowFunc](#arrowfunc) + * - [Closure](#closure) + * - [ByRef](#byref) + * - [Silent](#silent) + * - [RetIf](#retif) + * - [New](#new) + * - [Include](#include) + * - [Call](#call) + * - [Eval](#eval) + * - [Exit](#exit) + * - [Clone](#clone) + * - [Assign](#assign) + * - [AssignRef](#assignref) * - [Array](#array) + * - [List](#list) * - [Variable](#variable) * - [Variadic](#variadic) - * - [ConstRef](#constref) * - [Yield](#yield) * - [YieldFrom](#yieldfrom) + * - [Print](#print) + * - [Isset](#isset) + * - [Empty](#empty) * - [Lookup](#lookup) * - [PropertyLookup](#propertylookup) * - [StaticLookup](#staticlookup) @@ -37,7 +65,6 @@ var Position = require('./ast/position'); * - [Pre](#pre) * - [Post](#post) * - [Bin](#bin) - * - [Parenthesis](#parenthesis) * - [Unary](#unary) * - [Cast](#cast) * - [Literal](#literal) @@ -49,16 +76,19 @@ var Position = require('./ast/position'); * - [Nowdoc](#nowdoc) * - [Encapsed](#encapsed) * - [Statement](#statement) - * - [Eval](#eval) - * - [Exit](#exit) + * - [ConstantStatement](#constantstatement) + * - [ClassConstant](#classconstant) + * - [Return](#return) + * - [Label](#label) + * - [Continue](#continue) + * - [Case](#case) + * - [Break](#break) + * - [Echo](#echo) + * - [Unset](#unset) * - [Halt](#halt) - * - [Clone](#clone) * - [Declare](#declare) * - [Global](#global) * - [Static](#static) - * - [Include](#include) - * - [Assign](#assign) - * - [RetIf](#retif) * - [If](#if) * - [Do](#do) * - [While](#while) @@ -66,87 +96,62 @@ var Position = require('./ast/position'); * - [Foreach](#foreach) * - [Switch](#switch) * - [Goto](#goto) - * - [Silent](#silent) * - [Try](#try) * - [Catch](#catch) * - [Throw](#throw) - * - [Call](#call) - * - [Closure](#closure) - * - [New](#new) * - [UseGroup](#usegroup) * - [UseItem](#useitem) * - [Block](#block) * - [Program](#program) * - [Namespace](#namespace) - * - [Sys](#sys) - * - [Echo](#echo) - * - [List](#list) - * - [Print](#print) - * - [Isset](#isset) - * - [Unset](#unset) - * - [Empty](#empty) + * - [PropertyStatement](#propertystatement) + * - [Property](#property) * - [Declaration](#declaration) * - [Class](#class) * - [Interface](#interface) * - [Trait](#trait) - * - [Constant](#constant) - * - [ClassConstant](#classconstant) * - [Function](#function) * - [Method](#method) * - [Parameter](#parameter) - * - [Property](#property) * --- */ /** * The AST builder class * @constructor AST + * @memberOf module:php-parser + * @tutorial AST * @property {Boolean} withPositions - Should locate any node (by default false) * @property {Boolean} withSource - Should extract the node original code (by default false) */ -var AST = function(withPositions, withSource) { +const AST = function (withPositions, withSource) { this.withPositions = withPositions; this.withSource = withSource; }; -/** - * Create a position node from specified parser - * including it's lexer current state - * @param {Parser} - * @return {Position} - * @private - */ -AST.prototype.position = function(parser) { - return new Position( - parser.lexer.yylloc.first_line, - parser.lexer.yylloc.first_column, - parser.lexer.yylloc.first_offset - ); -}; - - // operators in ascending order of precedence AST.precedence = {}; -var binOperatorsPrecedence = [ - ['or'], - ['xor'], - ['and'], - ['='], - ['?'], - ['??'], - ['||'], - ['&&'], - ['|'], - ['^'], - ['&'], - ['==', '!=', '===', '!==', /* '<>', */ '<=>'], - ['<', '<=', '>', '>='], - ['<<', '>>'], - ['+', '-', '.'], - ['*', '/', '%'], - ['!'], - ['instanceof'], - // TODO: typecasts +[ + ["or"], + ["xor"], + ["and"], + ["="], + ["?"], + ["??"], + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "!=", "===", "!==", /* '<>', */ "<=>"], + ["<", "<=", ">", ">="], + ["<<", ">>"], + ["+", "-", "."], + ["*", "/", "%"], + ["!"], + ["instanceof"], + ["cast", "silent"], + ["**"], // TODO: [ (array) // TODO: clone, new ].forEach(function (list, index) { @@ -155,113 +160,225 @@ var binOperatorsPrecedence = [ }); }); +/** + * @private + * @function AST#isRightAssociative + * @memberOf module:php-parser + * @param operator + * @return {boolean} + */ +AST.prototype.isRightAssociative = function (operator) { + return operator === "**" || operator === "??"; +}; + +/** + * Change parent node informations after swapping childs + * @private + * @function AST#swapLocations + * @memberOf module:php-parser + */ +AST.prototype.swapLocations = function (target, first, last, parser) { + if (this.withPositions) { + target.loc.start = first.loc.start; + target.loc.end = last.loc.end; + if (this.withSource) { + target.loc.source = parser.lexer._input.substring( + target.loc.start.offset, + target.loc.end.offset, + ); + } + } +}; + +/** + * Includes locations from first & last into the target + * @private + * @function AST#resolveLocations + * @memberOf module:php-parser + */ +AST.prototype.resolveLocations = function (target, first, last, parser) { + if (this.withPositions) { + if (target.loc.start.offset > first.loc.start.offset) { + target.loc.start = first.loc.start; + } + /* istanbul ignore next */ + if (target.loc.end.offset < last.loc.end.offset) { + target.loc.end = last.loc.end; + } + if (this.withSource) { + target.loc.source = parser.lexer._input.substring( + target.loc.start.offset, + target.loc.end.offset, + ); + } + } +}; /** * Check and fix precence, by default using right + * @private + * @function AST#resolvePrecedence + * @memberOf module:php-parser */ -AST.prototype.resolvePrecedence = function(result) { - var buffer; +AST.prototype.resolvePrecedence = function (result, parser) { + let buffer, lLevel, rLevel; // handling precendence - if (result.kind === 'bin') { - if (result.right) { - if (result.right.kind === 'bin') { - var lLevel = AST.precedence[result.type]; - var rLevel = AST.precedence[result.right.type]; - if (lLevel && rLevel && rLevel <= lLevel) { + if (result.kind === "call") { + // including what argument into location + this.resolveLocations(result, result.what, result, parser); + } else if ( + result.kind === "propertylookup" || + result.kind === "staticlookup" || + (result.kind === "offsetlookup" && result.offset) + ) { + // including what argument into location + this.resolveLocations(result, result.what, result.offset, parser); + } else if (result.kind === "bin") { + if (result.right && !result.right.parenthesizedExpression) { + if (result.right.kind === "bin") { + lLevel = AST.precedence[result.type]; + rLevel = AST.precedence[result.right.type]; + if ( + lLevel && + rLevel && + rLevel <= lLevel && + (result.type !== result.right.type || + !this.isRightAssociative(result.type)) + ) { // https://github.com/glayzzle/php-parser/issues/79 // shift precedence buffer = result.right; result.right = result.right.left; - buffer.left = this.resolvePrecedence(result); + this.swapLocations(result, result.left, result.right, parser); + buffer.left = this.resolvePrecedence(result, parser); + this.swapLocations(buffer, buffer.left, buffer.right, parser); result = buffer; } - } else if (result.right.kind === 'retif') { - var lLevel = AST.precedence[result.type]; - var rLevel = AST.precedence['?']; + } else if (result.right.kind === "retif") { + lLevel = AST.precedence[result.type]; + rLevel = AST.precedence["?"]; if (lLevel && rLevel && rLevel <= lLevel) { buffer = result.right; result.right = result.right.test; - buffer.test = this.resolvePrecedence(result); + this.swapLocations(result, result.left, result.right, parser); + buffer.test = this.resolvePrecedence(result, parser); + this.swapLocations(buffer, buffer.test, buffer.falseExpr, parser); result = buffer; } } } - } else if (result.kind === 'unary') { + } else if ( + (result.kind === "silent" || result.kind === "cast") && + result.expr && + !result.expr.parenthesizedExpression + ) { + // https://github.com/glayzzle/php-parser/issues/172 + if (result.expr.kind === "bin") { + buffer = result.expr; + result.expr = result.expr.left; + this.swapLocations(result, result, result.expr, parser); + buffer.left = this.resolvePrecedence(result, parser); + this.swapLocations(buffer, buffer.left, buffer.right, parser); + result = buffer; + } else if (result.expr.kind === "retif") { + buffer = result.expr; + result.expr = result.expr.test; + this.swapLocations(result, result, result.expr, parser); + buffer.test = this.resolvePrecedence(result, parser); + this.swapLocations(buffer, buffer.test, buffer.falseExpr, parser); + result = buffer; + } + } else if (result.kind === "unary") { // https://github.com/glayzzle/php-parser/issues/75 - if (result.what) { - // unary precedence is allways lower - if (result.what.kind === 'bin') { + if (result.what && !result.what.parenthesizedExpression) { + // unary precedence is always lower + if (result.what.kind === "bin") { buffer = result.what; result.what = result.what.left; - buffer.left = this.resolvePrecedence(result); + this.swapLocations(result, result, result.what, parser); + buffer.left = this.resolvePrecedence(result, parser); + this.swapLocations(buffer, buffer.left, buffer.right, parser); result = buffer; - } else if (result.what.kind === 'retif') { + } else if (result.what.kind === "retif") { buffer = result.what; result.what = result.what.test; - buffer.test = this.resolvePrecedence(result); + this.swapLocations(result, result, result.what, parser); + buffer.test = this.resolvePrecedence(result, parser); + this.swapLocations(buffer, buffer.test, buffer.falseExpr, parser); result = buffer; } } - } else if (result.kind === 'retif') { + } else if (result.kind === "retif") { // https://github.com/glayzzle/php-parser/issues/77 - if (result.falseExpr && result.falseExpr.kind === 'retif') { + if ( + result.falseExpr && + result.falseExpr.kind === "retif" && + !result.falseExpr.parenthesizedExpression + ) { buffer = result.falseExpr; result.falseExpr = buffer.test; - buffer.test = this.resolvePrecedence(result); + this.swapLocations(result, result.test, result.falseExpr, parser); + buffer.test = this.resolvePrecedence(result, parser); + this.swapLocations(buffer, buffer.test, buffer.falseExpr, parser); result = buffer; } - } else if (result.kind === 'assign') { + } else if (result.kind === "assign") { // https://github.com/glayzzle/php-parser/issues/81 - if (result.right && result.right.kind === 'bin') { - var lLevel = AST.precedence['=']; - var rLevel = AST.precedence[result.right.type]; + if ( + result.right && + result.right.kind === "bin" && + !result.right.parenthesizedExpression + ) { + lLevel = AST.precedence["="]; + rLevel = AST.precedence[result.right.type]; // only shifts with and, xor, or if (lLevel && rLevel && rLevel < lLevel) { buffer = result.right; result.right = result.right.left; buffer.left = result; + this.swapLocations(buffer, buffer.left, result.right, parser); result = buffer; } } + } else if (result.kind === "expressionstatement") { + this.swapLocations(result, result.expression, result, parser); } return result; }; /** * Prepares an AST node + * @private + * @function AST#prepare + * @memberOf module:php-parser * @param {String|null} kind - Defines the node type - * (if null, the kind must be passed at the function call) + * @param {*} docs - (if null, the kind must be passed at the function call) * @param {Parser} parser - The parser instance (use for extracting locations) * @return {Function} */ -AST.prototype.prepare = function(kind, parser) { - var start = null; +AST.prototype.prepare = function (kind, docs, parser) { + let start = null; if (this.withPositions || this.withSource) { - start = this.position(parser); + start = parser.position(); } - var self = this; + const self = this; // returns the node - return function() { - var location = null; - var args = Array.prototype.slice.call(arguments); + const result = function () { + let location = null; + const args = Array.prototype.slice.call(arguments); + args.push(docs); if (self.withPositions || self.withSource) { - var src = null; + let src = null; if (self.withSource) { - src = parser.lexer._input.substring( - start.offset, - parser.lexer.yylloc.prev_offset - ); - } - if (self.withPositions) { - location = new Location(src, start, new Position( - parser.lexer.yylloc.prev_line, - parser.lexer.yylloc.prev_column, - parser.lexer.yylloc.prev_offset - )); - } else { - location = new Location(src, null, null); + src = parser.lexer._input.substring(start.offset, parser.prev[2]); } - // last argument is allways the location + // if with source, need location on swapLocations function + location = new Location( + src, + start, + new Position(parser.prev[0], parser.prev[1], parser.prev[2]), + ); + // last argument is always the location args.push(location); } // handle lazy kind definitions @@ -269,108 +386,206 @@ AST.prototype.prepare = function(kind, parser) { kind = args.shift(); } // build the object - var node = self[kind]; - if (typeof node !== 'function') { - throw new Error('Undefined node "'+kind+'"'); + const node = self[kind]; + if (typeof node !== "function") { + throw new Error('Undefined node "' + kind + '"'); + } + const astNode = Object.create(node.prototype); + node.apply(astNode, args); + result.instance = astNode; + /* istanbul ignore next */ + if (result.trailingComments) { + // buffer of trailingComments + astNode.trailingComments = result.trailingComments; + } + if (typeof result.postBuild === "function") { + result.postBuild(astNode); + } + if (parser.debug) { + delete self.stack[result.stackUid]; + } + return self.resolvePrecedence(astNode, parser); + }; + if (parser.debug) { + if (!this.stack) { + this.stack = {}; + this.stackUid = 1; + } + this.stack[++this.stackUid] = { + position: start, + stack: new Error().stack.split("\n").slice(3, 5), + }; + result.stackUid = this.stackUid; + } + + /** + * Sets a list of trailing comments + * @private + * @param {*} docs + */ + result.setTrailingComments = function (docs) { + if (result.instance) { + // already created + result.instance.setTrailingComments(docs); + } else { + result.trailingComments = docs; } - var result = Object.create(node.prototype); - node.apply(result, args); - return self.resolvePrecedence(result); }; + + /** + * Release a node without using it on the AST + * @private + * @param {*} target + */ + result.destroy = function (target) { + if (docs) { + // release current docs stack + if (target) { + if (!target.leadingComments) { + target.leadingComments = docs; + } else { + target.leadingComments = docs.concat(target.leadingComments); + } + } else { + parser._docIndex = parser._docs.length - docs.length; + } + } + if (parser.debug) { + delete self.stack[result.stackUid]; + } + }; + return result; +}; + +AST.prototype.checkNodes = function () { + const errors = []; + for (const k in this.stack) { + if (Object.prototype.hasOwnProperty.call(this.stack, k)) { + this.stack[k].key = k; + errors.push(this.stack[k]); + } + } + this.stack = {}; + return errors; }; // Define all AST nodes [ - require('./ast/array'), - require('./ast/assign'), - require('./ast/bin'), - require('./ast/block'), - require('./ast/boolean'), - require('./ast/break'), - require('./ast/call'), - require('./ast/case'), - require('./ast/cast'), - require('./ast/catch'), - require('./ast/class'), - require('./ast/classconstant'), - require('./ast/clone'), - require('./ast/closure'), - require('./ast/constant'), - require('./ast/constref'), - require('./ast/continue'), - require('./ast/declaration'), - require('./ast/declare'), - require('./ast/do'), - require('./ast/doc'), - require('./ast/echo'), - require('./ast/empty'), - require('./ast/encapsed'), - require('./ast/entry'), - require('./ast/error'), - require('./ast/eval'), - require('./ast/exit'), - require('./ast/expression'), - require('./ast/for'), - require('./ast/foreach'), - require('./ast/function'), - require('./ast/global'), - require('./ast/goto'), - require('./ast/halt'), - require('./ast/identifier'), - require('./ast/if'), - require('./ast/include'), - require('./ast/inline'), - require('./ast/interface'), - require('./ast/isset'), - require('./ast/label'), - require('./ast/list'), - require('./ast/literal'), - require('./ast/lookup'), - require('./ast/magic'), - require('./ast/method'), - require('./ast/namespace'), - require('./ast/new'), - require('./ast/node'), - require('./ast/nowdoc'), - require('./ast/number'), - require('./ast/offsetlookup'), - require('./ast/operation'), - require('./ast/parameter'), - require('./ast/parenthesis'), - require('./ast/post'), - require('./ast/pre'), - require('./ast/print'), - require('./ast/program'), - require('./ast/property'), - require('./ast/propertylookup'), - require('./ast/retif'), - require('./ast/return'), - require('./ast/silent'), - require('./ast/statement'), - require('./ast/static'), - require('./ast/staticlookup'), - require('./ast/string'), - require('./ast/switch'), - require('./ast/sys'), - require('./ast/throw'), - require('./ast/trait'), - require('./ast/traitalias'), - require('./ast/traitprecedence'), - require('./ast/traituse'), - require('./ast/try'), - require('./ast/unary'), - require('./ast/unset'), - require('./ast/usegroup'), - require('./ast/useitem'), - require('./ast/variable'), - require('./ast/variadic'), - require('./ast/while'), - require('./ast/yield'), - require('./ast/yieldfrom') + require("./ast/array"), + require("./ast/arrowfunc"), + require("./ast/assign"), + require("./ast/assignref"), + require("./ast/attribute"), + require("./ast/attrgroup"), + require("./ast/bin"), + require("./ast/block"), + require("./ast/boolean"), + require("./ast/break"), + require("./ast/byref"), + require("./ast/call"), + require("./ast/case"), + require("./ast/cast"), + require("./ast/catch"), + require("./ast/class"), + require("./ast/classconstant"), + require("./ast/clone"), + require("./ast/closure"), + require("./ast/comment"), + require("./ast/commentblock"), + require("./ast/commentline"), + require("./ast/constant"), + require("./ast/constantstatement"), + require("./ast/continue"), + require("./ast/declaration"), + require("./ast/declare"), + require("./ast/declaredirective"), + require("./ast/do"), + require("./ast/echo"), + require("./ast/empty"), + require("./ast/encapsed"), + require("./ast/encapsedpart"), + require("./ast/entry"), + require("./ast/enum"), + require("./ast/enumcase"), + require("./ast/error"), + require("./ast/eval"), + require("./ast/exit"), + require("./ast/expression"), + require("./ast/expressionstatement"), + require("./ast/for"), + require("./ast/foreach"), + require("./ast/function"), + require("./ast/global"), + require("./ast/goto"), + require("./ast/halt"), + require("./ast/identifier"), + require("./ast/if"), + require("./ast/include"), + require("./ast/inline"), + require("./ast/interface"), + require("./ast/intersectiontype"), + require("./ast/isset"), + require("./ast/label"), + require("./ast/list"), + require("./ast/literal"), + require("./ast/lookup"), + require("./ast/magic"), + require("./ast/match"), + require("./ast/matcharm"), + require("./ast/method"), + require("./ast/name"), + require("./ast/namespace"), + require("./ast/namedargument"), + require("./ast/new"), + require("./ast/node"), + require("./ast/noop"), + require("./ast/nowdoc"), + require("./ast/nullkeyword"), + require("./ast/nullsafepropertylookup"), + require("./ast/number"), + require("./ast/offsetlookup"), + require("./ast/operation"), + require("./ast/parameter"), + require("./ast/parentreference"), + require("./ast/post"), + require("./ast/pre"), + require("./ast/print"), + require("./ast/program"), + require("./ast/property"), + require("./ast/propertylookup"), + require("./ast/propertystatement"), + require("./ast/reference"), + require("./ast/retif"), + require("./ast/return"), + require("./ast/selfreference"), + require("./ast/silent"), + require("./ast/statement"), + require("./ast/static"), + require("./ast/staticvariable"), + require("./ast/staticlookup"), + require("./ast/staticreference"), + require("./ast/string"), + require("./ast/switch"), + require("./ast/throw"), + require("./ast/trait"), + require("./ast/traitalias"), + require("./ast/traitprecedence"), + require("./ast/traituse"), + require("./ast/try"), + require("./ast/typereference"), + require("./ast/unary"), + require("./ast/uniontype"), + require("./ast/unset"), + require("./ast/usegroup"), + require("./ast/useitem"), + require("./ast/variable"), + require("./ast/variadic"), + require("./ast/variadicplaceholder"), + require("./ast/while"), + require("./ast/yield"), + require("./ast/yieldfrom"), ].forEach(function (ctor) { - var kind = ctor.prototype.constructor.name.toLowerCase(); - if (kind[0] === '_') kind = kind.substring(1); - AST.prototype[kind] = ctor; + AST.prototype[ctor.kind] = ctor; }); module.exports = AST; diff --git a/src/ast/array.js b/src/ast/array.js index 610b69d29..ce518aa79 100644 --- a/src/ast/array.js +++ b/src/ast/array.js @@ -1,15 +1,17 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Expr = require('./expression'); -var KIND = 'array'; +const Expr = require("./expression"); +const KIND = "array"; /** * Defines an array structure * @constructor Array + * @memberOf module:php-parser * @example * // PHP code : * [1, 'foo' => 'bar', 3] @@ -18,28 +20,25 @@ var KIND = 'array'; * { * "kind": "array", * "shortForm": true - * "items": [{ - * "kind": "entry", - * "key": null, - * "value": {"kind": "number", "value": "1"} - * }, { - * "kind": "entry", - * "key": {"kind": "string", "value": "foo", "isDoubleQuote": false}, - * "value": {"kind": "string", "value": "bar", "isDoubleQuote": false} - * }, { - * "kind": "entry", - * "key": null, - * "value": {"kind": "number", "value": "3"} - * }] + * "items": [ + * {"kind": "number", "value": "1"}, + * { + * "kind": "entry", + * "key": {"kind": "string", "value": "foo", "isDoubleQuote": false}, + * "value": {"kind": "string", "value": "bar", "isDoubleQuote": false} + * }, + * {"kind": "number", "value": "3"} + * ] * } * @extends {Expression} - * @property {Entry[]} items List of array items + * @property {Array} items List of array items * @property {boolean} shortForm Indicate if the short array syntax is used, ex `[]` instead `array()` */ -var Array = Expr.extends(function Array(shortForm, items, location) { - Expr.apply(this, [KIND, location]); - this.items = items; - this.shortForm = shortForm; -}); - -module.exports = Array; +module.exports = Expr.extends( + KIND, + function Array(shortForm, items, docs, location) { + Expr.apply(this, [KIND, docs, location]); + this.items = items; + this.shortForm = shortForm; + }, +); diff --git a/src/ast/arrowfunc.js b/src/ast/arrowfunc.js new file mode 100644 index 000000000..695b6ef6a --- /dev/null +++ b/src/ast/arrowfunc.js @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Expression = require("./expression"); +const KIND = "arrowfunc"; + +/** + * Defines an arrow function (it's like a closure) + * @constructor ArrowFunc + * @memberOf module:php-parser + * @extends {Expression} + * @property {Parameter[]} arguments + * @property {Identifier} type + * @property {Expression} body + * @property {boolean} byref + * @property {boolean} nullable + * @property {boolean} isStatic + */ +module.exports = Expression.extends( + KIND, + function Closure( + args, + byref, + body, + type, + nullable, + isStatic, + docs, + location, + ) { + Expression.apply(this, [KIND, docs, location]); + this.arguments = args; + this.byref = byref; + this.body = body; + this.type = type; + this.nullable = nullable; + this.isStatic = isStatic || false; + }, +); diff --git a/src/ast/assign.js b/src/ast/assign.js index c8a7bd4c2..4cf6a6857 100644 --- a/src/ast/assign.js +++ b/src/ast/assign.js @@ -1,25 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Statement = require('./statement'); -var KIND = 'assign'; +const Expression = require("./expression"); +const KIND = "assign"; /** * Assigns a value to the specified target * @constructor Assign - * @extends {Statement} + * @memberOf module:php-parser + * @extends {Expression} * @property {Expression} left * @property {Expression} right * @property {String} operator */ -var Assign = Statement.extends(function Assign(left, right, operator, location) { - Statement.apply(this, [KIND, location]); - this.operator = operator; - this.left = left; - this.right = right; -}); - -module.exports = Assign; +module.exports = Expression.extends( + KIND, + function Assign(left, right, operator, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.left = left; + this.right = right; + this.operator = operator; + }, +); diff --git a/src/ast/assignref.js b/src/ast/assignref.js new file mode 100644 index 000000000..668bd058a --- /dev/null +++ b/src/ast/assignref.js @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Expression = require("./expression"); +const KIND = "assignref"; + +/** + * Assigns a value to the specified target + * @constructor AssignRef + * @memberOf module:php-parser + * @extends {Expression} + * @property {Expression} left + * @property {Expression} right + * @property {String} operator + */ +module.exports = Expression.extends( + KIND, + function AssignRef(left, right, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.left = left; + this.right = right; + }, +); diff --git a/src/ast/attrgroup.js b/src/ast/attrgroup.js new file mode 100644 index 000000000..6ce01f061 --- /dev/null +++ b/src/ast/attrgroup.js @@ -0,0 +1,21 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Node = require("./node"); +const KIND = "attrgroup"; + +/** + * Attribute group + * @memberOf module:php-parser + * @constructor AttrGroup + * @extends {Node} + * @property {Attribute[]} attrs + */ +module.exports = Node.extends(KIND, function AttrGroup(attrs, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.attrs = attrs || []; +}); diff --git a/src/ast/attribute.js b/src/ast/attribute.js new file mode 100644 index 000000000..f617bb6d1 --- /dev/null +++ b/src/ast/attribute.js @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Node = require("./node"); +const KIND = "attribute"; + +/** + * Attribute Value + * @memberOf module:php-parser + * @constructor Attribute + * @extends {Node} + * @property {String} name + * @property {Parameter[]} args + */ +module.exports = Node.extends( + KIND, + function Attribute(name, args, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.name = name; + this.args = args; + }, +); diff --git a/src/ast/bin.js b/src/ast/bin.js index 78981edd7..6221f4843 100644 --- a/src/ast/bin.js +++ b/src/ast/bin.js @@ -1,25 +1,27 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Operation = require('./operation'); -var KIND = 'bin'; +const Operation = require("./operation"); +const KIND = "bin"; /** * Binary operations * @constructor Bin + * @memberOf module:php-parser * @extends {Operation} * @property {String} type * @property {Expression} left * @property {Expression} right */ -var Bin = Operation.extends(function Bin(type, left, right, location) { - Operation.apply(this, [KIND, location]); - this.type = type; - this.left = left; - this.right = right; -}); - -module.exports = Bin; +module.exports = Operation.extends( + KIND, + function Bin(type, left, right, docs, location) { + Operation.apply(this, [KIND, docs, location]); + this.type = type; + this.left = left; + this.right = right; + }, +); diff --git a/src/ast/block.js b/src/ast/block.js index a40e9d3af..1a51712f9 100644 --- a/src/ast/block.js +++ b/src/ast/block.js @@ -1,21 +1,24 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Statement = require('./statement'); -var KIND = 'block'; +const Statement = require("./statement"); +const KIND = "block"; /** * A block statement, i.e., a sequence of statements surrounded by braces. * @constructor Block + * @memberOf module:php-parser * @extends {Statement} * @property {Node[]} children */ -var Block = Statement.extends(function Block(kind, children, location) { - Statement.apply(this, [kind || KIND, location]); - this.children = children; -}); - -module.exports = Block; +module.exports = Statement.extends( + KIND, + function Block(kind, children, docs, location) { + Statement.apply(this, [kind || KIND, docs, location]); + this.children = children.filter(Boolean); + }, +); diff --git a/src/ast/boolean.js b/src/ast/boolean.js index c045b069e..9480d662d 100644 --- a/src/ast/boolean.js +++ b/src/ast/boolean.js @@ -1,19 +1,23 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Literal = require('./literal'); -var KIND = 'boolean'; +const Literal = require("./literal"); +const KIND = "boolean"; /** * Defines a boolean value (true/false) * @constructor Boolean + * @memberOf module:php-parser * @extends {Literal} + * @property {boolean} value */ -var Boolean = Literal.extends(function Boolean(value, location) { - Literal.apply(this, [KIND, value, location]); -}); - -module.exports = Boolean; +module.exports = Literal.extends( + KIND, + function Boolean(value, raw, docs, location) { + Literal.apply(this, [KIND, value, raw, docs, location]); + }, +); diff --git a/src/ast/break.js b/src/ast/break.js index 9efd19a5d..2e98e2515 100644 --- a/src/ast/break.js +++ b/src/ast/break.js @@ -1,21 +1,21 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Node = require('./node'); -var KIND = 'break'; + +const Statement = require("./statement"); +const KIND = "break"; /** * A break statement * @constructor Break - * @extends {Node} + * @memberOf module:php-parser + * @extends {Statement} * @property {Number|Null} level */ -var Break = Node.extends(function Break(level, location) { - Node.apply(this, [KIND, location]); +module.exports = Statement.extends(KIND, function Break(level, docs, location) { + Statement.apply(this, [KIND, docs, location]); this.level = level; }); - -module.exports = Break; diff --git a/src/ast/byref.js b/src/ast/byref.js new file mode 100644 index 000000000..89cfb98c2 --- /dev/null +++ b/src/ast/byref.js @@ -0,0 +1,21 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Expression = require("./expression"); +const KIND = "byref"; + +/** + * Passing by Reference - so the function can modify the variable + * @constructor ByRef + * @memberOf module:php-parser + * @extends {Expression} + * @property {ExpressionStatement} what + */ +module.exports = Expression.extends(KIND, function ByRef(what, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.what = what; +}); diff --git a/src/ast/call.js b/src/ast/call.js index 6e44333f7..51daf3485 100644 --- a/src/ast/call.js +++ b/src/ast/call.js @@ -1,24 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'call'; +const Expression = require("./expression"); +const KIND = "call"; /** * Executes a call statement * @constructor Call - * @extends {Statement} - * @property {Identifier|Variable|??} what - * @property {Arguments[]} arguments + * @memberOf module:php-parser + * @extends {Expression} + * @property {Identifier|Variable} what + * @property {Expression[]} arguments */ -var Call = Statement.extends(function Call(what, args, location) { - Statement.apply(this, [KIND, location]); - this.what = what; - this.arguments = args; -}); - -module.exports = Call; +module.exports = Expression.extends( + KIND, + function Call(what, args, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.what = what; + this.arguments = args; + }, +); diff --git a/src/ast/case.js b/src/ast/case.js index 126be6728..8e25b0537 100644 --- a/src/ast/case.js +++ b/src/ast/case.js @@ -1,23 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Node = require('./node'); -var KIND = 'case'; + +const Statement = require("./statement"); +const KIND = "case"; /** * A switch case statement * @constructor Case - * @extends {Node} + * @memberOf module:php-parser + * @extends {Statement} * @property {Expression|null} test - if null, means that the default case * @property {Block|null} body */ -var Case = Node.extends(function Case(test, body, location) { - Node.apply(this, [KIND, location]); - this.test = test; - this.body = body; -}); - -module.exports = Case; +module.exports = Statement.extends( + KIND, + function Case(test, body, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.test = test; + this.body = body; + }, +); diff --git a/src/ast/cast.js b/src/ast/cast.js index 0b7b2a0f1..8dadffa0a 100644 --- a/src/ast/cast.js +++ b/src/ast/cast.js @@ -1,24 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Operation = require('./operation'); -var KIND = 'cast'; +const Operation = require("./operation"); +const KIND = "cast"; /** * Binary operations * @constructor Cast + * @memberOf module:php-parser * @extends {Operation} * @property {String} type - * @property {Expression} what + * @property {String} raw + * @property {Expression} expr */ -var Cast = Operation.extends(function Cast(type, what, location) { - Operation.apply(this, [KIND, location]); - this.type = type; - this.what = what; -}); - -module.exports = Cast; +module.exports = Operation.extends( + KIND, + function Cast(type, raw, expr, docs, location) { + Operation.apply(this, [KIND, docs, location]); + this.type = type; + this.raw = raw; + this.expr = expr; + }, +); diff --git a/src/ast/catch.js b/src/ast/catch.js index fe8f48253..4560ffb97 100644 --- a/src/ast/catch.js +++ b/src/ast/catch.js @@ -1,27 +1,29 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'catch'; +const Statement = require("./statement"); +const KIND = "catch"; /** * Defines a catch statement * @constructor Catch + * @memberOf module:php-parser * @extends {Statement} - * @property {Identifier[]} what + * @property {Name[]} what * @property {Variable} variable - * @property {Statement} body + * @property {Block} body * @see http://php.net/manual/en/language.exceptions.php */ -var Catch = Statement.extends(function Catch(body, what, variable, location) { - Statement.apply(this, [KIND, location]); - this.body = body; - this.what = what; - this.variable = variable; -}); - -module.exports = Catch; +module.exports = Statement.extends( + KIND, + function Catch(body, what, variable, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.body = body; + this.what = what; + this.variable = variable; + }, +); diff --git a/src/ast/class.js b/src/ast/class.js index 13b7aeab7..cfa620c2c 100644 --- a/src/ast/class.js +++ b/src/ast/class.js @@ -1,31 +1,36 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Declaration = require('./declaration'); -var KIND = 'class'; - +const Declaration = require("./declaration"); +const KIND = "class"; /** * A class definition * @constructor Class + * @memberOf module:php-parser * @extends {Declaration} * @property {Identifier|null} extends - * @property {Identifier[]} implements + * @property {Identifier[]|null} implements * @property {Declaration[]} body * @property {boolean} isAnonymous * @property {boolean} isAbstract * @property {boolean} isFinal + * @property {boolean} isReadonly + * @property {AttrGroup[]} attrGroups */ -var Class = Declaration.extends(function Class(name, ext, impl, body, flags, location) { - Declaration.apply(this, [KIND, name, location]); - this.isAnonymous = name ? false : true; - this.extends = ext; - this.implements = impl; - this.body = body; - this.parseFlags(flags); -}); - -module.exports = Class; +module.exports = Declaration.extends( + KIND, + function Class(name, ext, impl, body, flags, docs, location) { + Declaration.apply(this, [KIND, name, docs, location]); + this.isAnonymous = name ? false : true; + this.extends = ext; + this.implements = impl; + this.body = body; + this.attrGroups = []; + this.parseFlags(flags); + }, +); diff --git a/src/ast/classconstant.js b/src/ast/classconstant.js index 286da0827..bea667188 100644 --- a/src/ast/classconstant.js +++ b/src/ast/classconstant.js @@ -1,23 +1,71 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; + +const ConstantStatement = require("./constantstatement"); +const KIND = "classconstant"; -var Constant = require('./constant'); -var KIND = 'classconstant'; +const IS_UNDEFINED = ""; +const IS_PUBLIC = "public"; +const IS_PROTECTED = "protected"; +const IS_PRIVATE = "private"; /** * Defines a class/interface/trait constant * @constructor ClassConstant - * @extends {Constant} - * @property {boolean} isStatic + * @memberOf module:php-parser + * @extends {ConstantStatement} * @property {string} visibility + * @property {boolean} final + * @property {boolean} nullable + * @property {TypeReference|IntersectionType|UnionType|null} type + * @property {AttrGroup[]} attrGroups + */ +const ClassConstant = ConstantStatement.extends( + KIND, + function ClassConstant( + kind, + constants, + flags, + nullable, + type, + attrGroups, + docs, + location, + ) { + ConstantStatement.apply(this, [kind || KIND, constants, docs, location]); + this.parseFlags(flags); + this.nullable = nullable; + this.type = type; + this.attrGroups = attrGroups; + }, +); + +/** + * Generic flags parser + * @function + * @name ClassConstant#parseFlags + * @memberOf module:php-parser + * @param {Array} flags + * @return {void} */ -var ClassConstant = Constant.extends(function ClassConstant(name, value, flags, location) { - Constant.apply(this, [name, value, location]); - this.kind = KIND; - this.parseFlags(flags); -}); +ClassConstant.prototype.parseFlags = function (flags) { + if (flags[0] === -1) { + this.visibility = IS_UNDEFINED; + } else if (flags[0] === null) { + /* istanbul ignore next */ + this.visibility = null; + } else if (flags[0] === 0) { + this.visibility = IS_PUBLIC; + } else if (flags[0] === 1) { + this.visibility = IS_PROTECTED; + } else if (flags[0] === 2) { + this.visibility = IS_PRIVATE; + } + this.final = flags[2] === 2; +}; module.exports = ClassConstant; diff --git a/src/ast/clone.js b/src/ast/clone.js index 4467603dd..54ff3e37b 100644 --- a/src/ast/clone.js +++ b/src/ast/clone.js @@ -1,21 +1,21 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Statement = require('./statement'); -var KIND = 'clone'; +const Expression = require("./expression"); +const KIND = "clone"; /** * Defines a clone call * @constructor Clone - * @extends {Statement} + * @memberOf module:php-parser + * @extends {Expression} * @property {Expression} what */ -var Clone = Statement.extends(function Clone(what, location) { - Statement.apply(this, [KIND, location]); +module.exports = Expression.extends(KIND, function Clone(what, docs, location) { + Expression.apply(this, [KIND, docs, location]); this.what = what; }); - -module.exports = Clone; diff --git a/src/ast/closure.js b/src/ast/closure.js index 9573ac825..059f47e12 100644 --- a/src/ast/closure.js +++ b/src/ast/closure.js @@ -1,33 +1,47 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'closure'; + +const Expression = require("./expression"); +const KIND = "closure"; /** * Defines a closure * @constructor Closure - * @extends {Statement} + * @memberOf module:php-parser + * @extends {Expression} * @property {Parameter[]} arguments * @property {Variable[]} uses * @property {Identifier} type - * @property {boolean} byref + * @property {Boolean} byref * @property {boolean} nullable * @property {Block|null} body * @property {boolean} isStatic + * @property {AttrGroup[]} attrGroups */ -var Closure = Statement.extends(function Closure(args, byref, uses, type, nullable, isStatic, location) { - Statement.apply(this, [KIND, location]); - this.uses = uses; - this.arguments = args; - this.byref = byref; - this.type = type; - this.nullable = nullable; - this.isStatic = isStatic || false; - this.body = null; -}); - -module.exports = Closure; +module.exports = Expression.extends( + KIND, + function Closure( + args, + byref, + uses, + type, + nullable, + isStatic, + docs, + location, + ) { + Expression.apply(this, [KIND, docs, location]); + this.uses = uses; + this.arguments = args; + this.byref = byref; + this.type = type; + this.nullable = nullable; + this.isStatic = isStatic || false; + this.body = null; + this.attrGroups = []; + }, +); diff --git a/src/ast/comment.js b/src/ast/comment.js new file mode 100644 index 000000000..71f99fe0d --- /dev/null +++ b/src/ast/comment.js @@ -0,0 +1,23 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Node = require("./node"); + +/** + * Abstract documentation node (ComentLine or CommentBlock) + * @constructor Comment + * @memberOf module:php-parser + * @extends {Node} + * @property {String} value + */ +module.exports = Node.extends( + "comment", + function Comment(kind, value, docs, location) { + Node.apply(this, [kind, docs, location]); + this.value = value; + }, +); diff --git a/src/ast/commentblock.js b/src/ast/commentblock.js new file mode 100644 index 000000000..9b94b8326 --- /dev/null +++ b/src/ast/commentblock.js @@ -0,0 +1,22 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Comment = require("./comment"); +const KIND = "commentblock"; + +/** + * A comment block (multiline) + * @constructor CommentBlock + * @memberOf module:php-parser + * @extends {Comment} + */ +module.exports = Comment.extends( + KIND, + function CommentBlock(value, docs, location) { + Comment.apply(this, [KIND, value, docs, location]); + }, +); diff --git a/src/ast/commentline.js b/src/ast/commentline.js new file mode 100644 index 000000000..d92d6f2d1 --- /dev/null +++ b/src/ast/commentline.js @@ -0,0 +1,22 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Comment = require("./comment"); +const KIND = "commentline"; + +/** + * A single line comment + * @constructor CommentLine + * @memberOf module:php-parser + * @extends {Comment} + */ +module.exports = Comment.extends( + KIND, + function CommentLine(value, docs, location) { + Comment.apply(this, [KIND, value, docs, location]); + }, +); diff --git a/src/ast/constant.js b/src/ast/constant.js index a9a71958b..698a7b14e 100644 --- a/src/ast/constant.js +++ b/src/ast/constant.js @@ -1,21 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Declaration = require('./declaration'); -var KIND = 'constant'; +const Node = require("./node"); +const KIND = "constant"; /** - * Defines a namespace constant + * Defines a constant * @constructor Constant - * @extends {Declaration} - * @property {Node|null} value + * @memberOf module:php-parser + * @extends {Node} + * @property {string} name + * @property {Node|string|number|boolean|null} value */ -var Constant = Declaration.extends(function Constant(name, value, location) { - Declaration.apply(this, [KIND, name, location]); - this.value = value; -}); - -module.exports = Constant; +module.exports = Node.extends( + KIND, + function Constant(name, value, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.name = name; + this.value = value; + }, +); diff --git a/src/ast/constantstatement.js b/src/ast/constantstatement.js new file mode 100644 index 000000000..eac6ca245 --- /dev/null +++ b/src/ast/constantstatement.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Statement = require("./statement"); +const KIND = "constantstatement"; + +/** + * Declares a constants into the current scope + * @constructor ConstantStatement + * @memberOf module:php-parser + * @extends {Statement} + * @property {Constant[]} constants + */ +module.exports = Statement.extends( + KIND, + function ConstantStatement(kind, constants, docs, location) { + Statement.apply(this, [kind || KIND, docs, location]); + this.constants = constants; + }, +); diff --git a/src/ast/constref.js b/src/ast/constref.js deleted file mode 100644 index f97930dfc..000000000 --- a/src/ast/constref.js +++ /dev/null @@ -1,21 +0,0 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Expr = require('./expression'); -var KIND = 'constref'; - -/** - * A constant reference - * @constructor ConstRef - * @extends {Expression} - * @property {String|Node} name - */ -var ConstRef = Expr.extends(function ConstRef(identifier, location) { - Expr.apply(this, [KIND, location]); - this.name = identifier; -}); - -module.exports = ConstRef; diff --git a/src/ast/continue.js b/src/ast/continue.js index 65f2e9bff..8344bc1b4 100644 --- a/src/ast/continue.js +++ b/src/ast/continue.js @@ -1,21 +1,24 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Node = require('./node'); -var KIND = 'continue'; + +const Statement = require("./statement"); +const KIND = "continue"; /** * A continue statement * @constructor Continue - * @extends {Node} - * @property {Number|Null} level + * @memberOf module:php-parser + * @extends {Statement} + * @property {number|null} level */ -var Continue = Node.extends(function Continue(level, location) { - Node.apply(this, [KIND, location]); - this.level = level; -}); - -module.exports = Continue; +module.exports = Statement.extends( + KIND, + function Continue(level, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.level = level; + }, +); diff --git a/src/ast/declaration.js b/src/ast/declaration.js index b3d64a434..33ffbf5e0 100644 --- a/src/ast/declaration.js +++ b/src/ast/declaration.js @@ -1,37 +1,52 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Statement = require('./statement'); -var KIND = 'declaration'; +const Statement = require("./statement"); +const KIND = "declaration"; -var IS_PUBLIC = 'public'; -var IS_PROTECTED = 'protected'; -var IS_PRIVATE = 'private'; +const IS_UNDEFINED = ""; +const IS_PUBLIC = "public"; +const IS_PROTECTED = "protected"; +const IS_PRIVATE = "private"; /** * A declaration statement (function, class, interface...) * @constructor Declaration + * @memberOf module:php-parser * @extends {Statement} - * @property {string} name + * @property {Identifier|string} name */ -var Declaration = Statement.extends(function Declaration(kind, name, location) { - Statement.apply(this, [kind || KIND, location]); - this.name = name; -}); +const Declaration = Statement.extends( + KIND, + function Declaration(kind, name, docs, location) { + Statement.apply(this, [kind || KIND, docs, location]); + this.name = name; + }, +); /** * Generic flags parser - * @param {Integer[]} flags + * @function + * @name Declaration#parseFlags + * @memberOf module:php-parser + * @param {Array} flags * @return {void} */ -Declaration.prototype.parseFlags = function(flags) { +Declaration.prototype.parseFlags = function (flags) { this.isAbstract = flags[2] === 1; this.isFinal = flags[2] === 2; - if (this.kind !== 'class') { - if (flags[0] === 0) { + this.isReadonly = flags[3] === 1; + if (this.kind !== "class") { + if (flags[0] === -1) { + this.visibility = IS_UNDEFINED; + } else if (flags[0] === null) { + /* istanbul ignore next */ + this.visibility = null; + } else if (flags[0] === 0) { this.visibility = IS_PUBLIC; } else if (flags[0] === 1) { this.visibility = IS_PROTECTED; diff --git a/src/ast/declare.js b/src/ast/declare.js index 0b974c6f2..dab989f21 100644 --- a/src/ast/declare.js +++ b/src/ast/declare.js @@ -1,26 +1,30 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Block = require('./block'); -var KIND = 'declare'; +const Block = require("./block"); +const KIND = "declare"; /** * The declare construct is used to set execution directives for a block of code * @constructor Declare + * @memberOf module:php-parser * @extends {Block} - * @property {Expression[]} what - * @property {String} mode + * @property {DeclareDirective[]} directives + * @property {string} mode * @see http://php.net/manual/en/control-structures.declare.php */ -var Declare = Block.extends(function Declare(what, body, mode, location) { - Block.apply(this, [KIND, body, location]); - this.what = what; - this.mode = mode; -}); - +const Declare = Block.extends( + KIND, + function Declare(directives, body, mode, docs, location) { + Block.apply(this, [KIND, body, docs, location]); + this.directives = directives; + this.mode = mode; + }, +); /** * The node is declared as a short tag syntax : @@ -30,9 +34,10 @@ var Declare = Block.extends(function Declare(what, body, mode, location) { * // some statements * enddeclare; * ``` - * @constant {String} MODE_SHORT + * @constant {String} Declare#MODE_SHORT + * @memberOf module:php-parser */ -Declare.MODE_SHORT = 'short'; +Declare.MODE_SHORT = "short"; /** * The node is declared bracket enclosed code : @@ -42,9 +47,10 @@ Declare.MODE_SHORT = 'short'; * // some statements * } * ``` - * @constant {String} MODE_BLOCK + * @constant {String} Declare#MODE_BLOCK + * @memberOf module:php-parser */ -Declare.MODE_BLOCK = 'block'; +Declare.MODE_BLOCK = "block"; /** * The node is declared as a simple statement. In order to make things simpler @@ -57,8 +63,9 @@ Declare.MODE_BLOCK = 'block'; * declare(ticks=2); * // some statements * ``` - * @constant {String} MODE_NONE + * @constant {String} Declare#MODE_NONE + * @memberOf module:php-parser */ -Declare.MODE_NONE = 'none'; +Declare.MODE_NONE = "none"; module.exports = Declare; diff --git a/src/ast/declaredirective.js b/src/ast/declaredirective.js new file mode 100644 index 000000000..ed65937d0 --- /dev/null +++ b/src/ast/declaredirective.js @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Node = require("./node"); +const KIND = "declaredirective"; + +/** + * Defines a constant + * @constructor DeclareDirective + * @memberOf module:php-parser + * @extends {Node} + * @property {Identifier} key + * @property {Node|string|number|boolean|null} value + */ +module.exports = Node.extends( + KIND, + function DeclareDirective(key, value, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.key = key; + this.value = value; + }, +); diff --git a/src/ast/do.js b/src/ast/do.js index 1e4a7902d..801790893 100644 --- a/src/ast/do.js +++ b/src/ast/do.js @@ -1,24 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'do'; +const Statement = require("./statement"); +const KIND = "do"; /** * Defines a do/while statement * @constructor Do + * @memberOf module:php-parser * @extends {Statement} * @property {Expression} test - * @property {Statement} body + * @property {Block | null} body */ -var Do = Statement.extends(function Do(test, body, location) { - Statement.apply(this, [KIND, location]); - this.test = test; - this.body = body; -}); - -module.exports = Do; +module.exports = Statement.extends( + KIND, + function Do(test, body, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.test = test; + this.body = body; + }, +); diff --git a/src/ast/doc.js b/src/ast/doc.js deleted file mode 100644 index 3c989fbfd..000000000 --- a/src/ast/doc.js +++ /dev/null @@ -1,23 +0,0 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Node = require('./node'); -var KIND = 'doc'; - -/** - * A comment or documentation - * @constructor Documentation - * @extends {Node} - * @property {Boolean} isDoc - * @property {String[]} lines - */ -var Doc = Node.extends(function Doc(isDoc, lines, location) { - Node.apply(this, [KIND, location]); - this.isDoc = isDoc; - this.lines = lines; -}); - -module.exports = Doc; diff --git a/src/ast/echo.js b/src/ast/echo.js index c0e92cb24..5bf5765bb 100644 --- a/src/ast/echo.js +++ b/src/ast/echo.js @@ -1,19 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Sys = require('./sys'); -var KIND = 'echo'; +const Statement = require("./statement"); +const KIND = "echo"; /** * Defines system based call * @constructor Echo - * @extends {Sys} + * @memberOf module:php-parser + * @property {boolean} shortForm + * @property {Expression[]} expressions + * @extends {Statement} */ -var Echo = Sys.extends(function Echo(args, location) { - Sys.apply(this, [KIND, args, location]); -}); - -module.exports = Echo; +module.exports = Statement.extends( + KIND, + function Echo(expressions, shortForm, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.shortForm = shortForm; + this.expressions = expressions; + }, +); diff --git a/src/ast/empty.js b/src/ast/empty.js index 992f824c5..d2c5809b7 100644 --- a/src/ast/empty.js +++ b/src/ast/empty.js @@ -1,19 +1,23 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Sys = require('./sys'); -var KIND = 'empty'; +const Expression = require("./expression"); +const KIND = "empty"; /** * Defines an empty check call * @constructor Empty - * @extends {Sys} + * @memberOf module:php-parser + * @extends {Expression} */ -var Empty = Sys.extends(function Empty(args, location) { - Sys.apply(this, [KIND, args, location]); -}); - -module.exports = Empty; +module.exports = Expression.extends( + KIND, + function Empty(expression, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.expression = expression; + }, +); diff --git a/src/ast/encapsed.js b/src/ast/encapsed.js index 1ca532525..ac34a4365 100644 --- a/src/ast/encapsed.js +++ b/src/ast/encapsed.js @@ -1,24 +1,29 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Literal = require('./literal'); -var KIND = 'encapsed'; +const Literal = require("./literal"); +const KIND = "encapsed"; /** * Defines an encapsed string (contains expressions) * @constructor Encapsed + * @memberOf module:php-parser * @extends {Literal} * @property {String} type - Defines the type of encapsed string (shell, heredoc, string) * @property {String|Null} label - The heredoc label, defined only when the type is heredoc + * @property {EncapsedPart[]} value */ -var Encapsed = Literal.extends(function Encapsed(value, type, location) { - Literal.apply(this, [KIND, value, location]); - this.type = type; -}); - +const Encapsed = Literal.extends( + KIND, + function Encapsed(value, raw, type, docs, location) { + Literal.apply(this, [KIND, value, raw, docs, location]); + this.type = type; + }, +); /** * The node is a double quote string : @@ -26,9 +31,10 @@ var Encapsed = Literal.extends(function Encapsed(value, type, location) { * bar_$baz; * ``` - * @constant {String} TYPE_OFFSET - `offset` + * @constant {String} Encapsed#TYPE_OFFSET - `offset` + * @memberOf module:php-parser */ -Encapsed.TYPE_OFFSET = 'offset'; - +Encapsed.TYPE_OFFSET = "offset"; module.exports = Encapsed; diff --git a/src/ast/encapsedpart.js b/src/ast/encapsedpart.js new file mode 100644 index 000000000..cb5d836b1 --- /dev/null +++ b/src/ast/encapsedpart.js @@ -0,0 +1,28 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Expression = require("./expression"); +const KIND = "encapsedpart"; + +/** + * Part of `Encapsed` node + * @constructor EncapsedPart + * @memberOf module:php-parser + * @extends {Expression} + * @property {Expression} expression + * @property {String} syntax + * @property {Boolean} curly + */ +module.exports = Expression.extends( + KIND, + function EncapsedPart(expression, syntax, curly, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.expression = expression; + this.syntax = syntax; + this.curly = curly; + }, +); diff --git a/src/ast/entry.js b/src/ast/entry.js index b2b65ce64..4300e2366 100644 --- a/src/ast/entry.js +++ b/src/ast/entry.js @@ -1,23 +1,30 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Node = require('./node'); -var KIND = 'entry'; +const Expression = require("./expression"); +const KIND = "entry"; /** * An array entry - see [Array](#array) + * @memberOf module:php-parser * @constructor Entry - * @extends {Node} + * @extends {Expression} * @property {Node|null} key The entry key/offset * @property {Node} value The entry value + * @property {Boolean} byRef By reference + * @property {Boolean} unpack Argument unpacking */ -var Entry = Node.extends(function Entry(key, value, location) { - Node.apply(this, [KIND, location]); - this.key = key; - this.value = value; -}); - -module.exports = Entry; +module.exports = Expression.extends( + KIND, + function Entry(key, value, byRef, unpack, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.key = key; + this.value = value; + this.byRef = byRef; + this.unpack = unpack; + }, +); diff --git a/src/ast/enum.js b/src/ast/enum.js new file mode 100644 index 000000000..eee63b58d --- /dev/null +++ b/src/ast/enum.js @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Declaration = require("./declaration"); +const KIND = "enum"; + +/** + * A enum definition + * @constructor Enum + * @memberOf module:php-parser + * @extends {Declaration} + * @property {Identifier|null} valueType + * @property {Identifier[]} implements + * @property {Declaration[]} body + * @property {AttrGroup[]} attrGroups + */ +module.exports = Declaration.extends( + KIND, + function Enum(name, valueType, impl, body, docs, location) { + Declaration.apply(this, [KIND, name, docs, location]); + this.valueType = valueType; + this.implements = impl; + this.body = body; + this.attrGroups = []; + }, +); diff --git a/src/ast/enumcase.js b/src/ast/enumcase.js new file mode 100644 index 000000000..a182d25a7 --- /dev/null +++ b/src/ast/enumcase.js @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Node = require("./node"); +const KIND = "enumcase"; + +/** + * Declares a cases into the current scope + * @constructor EnumCase + * @memberOf module:php-parser + * @extends {Node} + * @property {string} name + * @property {string|number|null} value + */ +module.exports = Node.extends( + KIND, + function EnumCase(name, value, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.name = name; + this.value = value; + }, +); diff --git a/src/ast/error.js b/src/ast/error.js index dae16b801..a715469c4 100644 --- a/src/ast/error.js +++ b/src/ast/error.js @@ -1,28 +1,30 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Node = require('./node'); -var KIND = 'error'; - +const Node = require("./node"); +const KIND = "error"; /** * Defines an error node (used only on silentMode) * @constructor Error + * @memberOf module:php-parser * @extends {Node} * @property {string} message * @property {number} line * @property {number|string} token * @property {string|array} expected */ -var Error = Node.extends(function Error(message, token, line, expected, location) { - Node.apply(this, [KIND, location]); - this.message = message; - this.token = token; - this.line = line; - this.expected = expected; -}); - -module.exports = Error; +module.exports = Node.extends( + KIND, + function Error(message, token, line, expected, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.message = message; + this.token = token; + this.line = line; + this.expected = expected; + }, +); diff --git a/src/ast/eval.js b/src/ast/eval.js index 90ac9226f..950414823 100644 --- a/src/ast/eval.js +++ b/src/ast/eval.js @@ -1,21 +1,24 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Statement = require('./statement'); -var KIND = 'eval'; +const Expression = require("./expression"); +const KIND = "eval"; /** * Defines an eval statement * @constructor Eval - * @extends {Statement} + * @memberOf module:php-parser + * @extends {Expression} * @property {Node} source */ -var Eval = Statement.extends(function Eval(source, location) { - Statement.apply(this, [KIND, location]); - this.source = source; -}); - -module.exports = Eval; +module.exports = Expression.extends( + KIND, + function Eval(source, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.source = source; + }, +); diff --git a/src/ast/exit.js b/src/ast/exit.js index 32b535351..3d895dd6e 100644 --- a/src/ast/exit.js +++ b/src/ast/exit.js @@ -1,21 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Statement = require('./statement'); -var KIND = 'exit'; +const Expression = require("./expression"); +const KIND = "exit"; /** * Defines an exit / die call * @constructor Exit - * @extends {Statement} - * @property {Node|null} status + * @memberOf module:php-parser + * @extends {Expression} + * @property {Node|null} expression + * @property {boolean} useDie */ -var Exit = Statement.extends(function Exit(status, location) { - Statement.apply(this, [KIND, location]); - this.status = status; -}); - -module.exports = Exit; +module.exports = Expression.extends( + KIND, + function Exit(expression, useDie, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.expression = expression; + this.useDie = useDie; + }, +); diff --git a/src/ast/expression.js b/src/ast/expression.js index bdad939b9..c64f16a6c 100644 --- a/src/ast/expression.js +++ b/src/ast/expression.js @@ -1,20 +1,20 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Node = require('./node'); -var KIND = 'expression'; +const Node = require("./node"); +const KIND = "expression"; /** * Any expression node. Since the left-hand side of an assignment may * be any expression in general, an expression can also be a pattern. * @constructor Expression + * @memberOf module:php-parser * @extends {Node} */ -var Expression = Node.extends(function Expression(kind, location) { - Node.apply(this, [kind || KIND, location]); +module.exports = Node.extends(KIND, function Expression(kind, docs, location) { + Node.apply(this, [kind || KIND, docs, location]); }); - -module.exports = Expression; diff --git a/src/ast/expressionstatement.js b/src/ast/expressionstatement.js new file mode 100644 index 000000000..77f40d51c --- /dev/null +++ b/src/ast/expressionstatement.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Statement = require("./statement"); +const KIND = "expressionstatement"; + +/** + * Defines an expression based statement + * @constructor ExpressionStatement + * @memberOf module:php-parser + * @extends {Statement} + * @property {Expression} expression + */ +module.exports = Statement.extends( + KIND, + function ExpressionStatement(expr, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.expression = expr; + }, +); diff --git a/src/ast/for.js b/src/ast/for.js index 6861bdc67..37ad87004 100644 --- a/src/ast/for.js +++ b/src/ast/for.js @@ -1,31 +1,33 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'for'; +const Statement = require("./statement"); +const KIND = "for"; /** * Defines a for iterator * @constructor For + * @memberOf module:php-parser * @extends {Statement} * @property {Expression[]} init * @property {Expression[]} test * @property {Expression[]} increment - * @property {Statement} body + * @property {Block | null} body * @property {boolean} shortForm * @see http://php.net/manual/en/control-structures.for.php */ -var For = Statement.extends(function For(init, test, increment, body, shortForm, location) { - Statement.apply(this, [KIND, location]); - this.init = init; - this.test = test; - this.increment = increment; - this.shortForm = shortForm; - this.body = body; -}); - -module.exports = For; +module.exports = Statement.extends( + KIND, + function For(init, test, increment, body, shortForm, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.init = init; + this.test = test; + this.increment = increment; + this.shortForm = shortForm; + this.body = body; + }, +); diff --git a/src/ast/foreach.js b/src/ast/foreach.js index 101543dbc..dbb70e0e5 100644 --- a/src/ast/foreach.js +++ b/src/ast/foreach.js @@ -1,31 +1,33 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'foreach'; +const Statement = require("./statement"); +const KIND = "foreach"; /** * Defines a foreach iterator * @constructor Foreach + * @memberOf module:php-parser * @extends {Statement} * @property {Expression} source * @property {Expression|null} key * @property {Expression} value - * @property {Statement} body + * @property {Block | null} body * @property {boolean} shortForm * @see http://php.net/manual/en/control-structures.foreach.php */ -var Foreach = Statement.extends(function Foreach(source, key, value, body, shortForm, location) { - Statement.apply(this, [KIND, location]); - this.source = source; - this.key = key; - this.value = value; - this.shortForm = shortForm; - this.body = body; -}); - -module.exports = Foreach; +module.exports = Statement.extends( + KIND, + function Foreach(source, key, value, body, shortForm, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.source = source; + this.key = key; + this.value = value; + this.shortForm = shortForm; + this.body = body; + }, +); diff --git a/src/ast/function.js b/src/ast/function.js index c082b9394..796903ab1 100644 --- a/src/ast/function.js +++ b/src/ast/function.js @@ -1,28 +1,34 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Declaration = require('./declaration'); -var KIND = 'function'; +const Declaration = require("./declaration"); +const KIND = "function"; /** * Defines a classic function * @constructor Function + * @memberOf module:php-parser * @extends {Declaration} * @property {Parameter[]} arguments * @property {Identifier} type * @property {boolean} byref * @property {boolean} nullable * @property {Block|null} body + * @property {AttrGroup[]} attrGroups */ -var fn = Declaration.extends(function _Function(name, args, byref, type, nullable, location) { - Declaration.apply(this, [KIND, name, location]); - this.arguments = args; - this.byref = byref; - this.type = type; - this.nullable = nullable; - this.body = null; -}); -module.exports = fn; +module.exports = Declaration.extends( + KIND, + function _Function(name, args, byref, type, nullable, docs, location) { + Declaration.apply(this, [KIND, name, docs, location]); + this.arguments = args; + this.byref = byref; + this.type = type; + this.nullable = nullable; + this.body = null; + this.attrGroups = []; + }, +); diff --git a/src/ast/global.js b/src/ast/global.js index 691309eb9..ba9692f53 100644 --- a/src/ast/global.js +++ b/src/ast/global.js @@ -1,21 +1,24 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'global'; + +const Statement = require("./statement"); +const KIND = "global"; /** * Imports a variable from the global scope * @constructor Global + * @memberOf module:php-parser * @extends {Statement} * @property {Variable[]} items */ -var Global = Statement.extends(function Global(items, location) { - Statement.apply(this, [KIND, location]); - this.items = items; -}); - -module.exports = Global; +module.exports = Statement.extends( + KIND, + function Global(items, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.items = items; + }, +); diff --git a/src/ast/goto.js b/src/ast/goto.js index e58509c0c..4e00653eb 100644 --- a/src/ast/goto.js +++ b/src/ast/goto.js @@ -1,23 +1,22 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'goto'; +const Statement = require("./statement"); +const KIND = "goto"; /** * Defines goto statement * @constructor Goto + * @memberOf module:php-parser * @extends {Statement} - * @property {String} label + * @property {string} label * @see {Label} */ -var Goto = Statement.extends(function Goto(label, location) { - Statement.apply(this, [KIND, location]); +module.exports = Statement.extends(KIND, function Goto(label, docs, location) { + Statement.apply(this, [KIND, docs, location]); this.label = label; }); - -module.exports = Goto; diff --git a/src/ast/halt.js b/src/ast/halt.js index d43d17ca2..acad687dc 100644 --- a/src/ast/halt.js +++ b/src/ast/halt.js @@ -1,23 +1,22 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'halt'; +const Statement = require("./statement"); +const KIND = "halt"; /** * Halts the compiler execution * @constructor Halt + * @memberOf module:php-parser * @extends {Statement} * @property {String} after - String after the halt statement * @see http://php.net/manual/en/function.halt-compiler.php */ -var Halt = Statement.extends(function Halt(after, location) { - Statement.apply(this, [KIND, location]); +module.exports = Statement.extends(KIND, function Halt(after, docs, location) { + Statement.apply(this, [KIND, docs, location]); this.after = after; }); - -module.exports = Halt; diff --git a/src/ast/identifier.js b/src/ast/identifier.js index 8510e092d..557c8f557 100644 --- a/src/ast/identifier.js +++ b/src/ast/identifier.js @@ -1,55 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Node = require('./node'); -var KIND = 'identifier'; +const Node = require("./node"); +const KIND = "identifier"; /** * Defines an identifier node * @constructor Identifier + * @memberOf module:php-parser * @extends {Node} * @property {string} name - * @property {string} resolution - */ -var Identifier = Node.extends(function Identifier(name, isRelative, location) { - Node.apply(this, [KIND, location]); - if (isRelative) { - this.resolution = Identifier.RELATIVE_NAME; - } else if (name.length === 1) { - this.resolution = Identifier.UNQUALIFIED_NAME; - } else if (name[0] === '') { - this.resolution = Identifier.FULL_QUALIFIED_NAME; - } else { - this.resolution = Identifier.QUALIFIED_NAME; - } - this.name = name.join('\\'); -}); - -/** - * This is an identifier without a namespace separator, such as Foo - * @constant {String} UNQUALIFIED_NAME - */ -Identifier.UNQUALIFIED_NAME = 'uqn'; -/** - * This is an identifier with a namespace separator, such as Foo\Bar - * @constant {String} QUALIFIED_NAME */ -Identifier.QUALIFIED_NAME = 'qn'; -/** - * This is an identifier with a namespace separator that begins with - * a namespace separator, such as \Foo\Bar. The namespace \Foo is also - * a fully qualified name. - * @constant {String} FULL_QUALIFIED_NAME - */ -Identifier.FULL_QUALIFIED_NAME = 'fqn'; -/** - * This is an identifier starting with namespace, such as namespace\Foo\Bar. - * @constant {String} RELATIVE_NAME - */ -Identifier.RELATIVE_NAME = 'rn'; - +const Identifier = Node.extends( + KIND, + function Identifier(name, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.name = name; + }, +); module.exports = Identifier; diff --git a/src/ast/if.js b/src/ast/if.js index 2bc99007f..c04b61246 100644 --- a/src/ast/if.js +++ b/src/ast/if.js @@ -1,28 +1,30 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'if'; +const Statement = require("./statement"); +const KIND = "if"; /** * Defines a if statement * @constructor If + * @memberOf module:php-parser * @extends {Statement} * @property {Expression} test * @property {Block} body * @property {Block|If|null} alternate * @property {boolean} shortForm */ -var If = Statement.extends(function If(test, body, alternate, shortForm, location) { - Statement.apply(this, [KIND, location]); - this.test = test; - this.body = body; - this.alternate = alternate; - this.shortForm = shortForm; -}); - -module.exports = If; +module.exports = Statement.extends( + KIND, + function If(test, body, alternate, shortForm, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.test = test; + this.body = body; + this.alternate = alternate; + this.shortForm = shortForm; + }, +); diff --git a/src/ast/include.js b/src/ast/include.js index ee4583aed..a6312cda1 100644 --- a/src/ast/include.js +++ b/src/ast/include.js @@ -1,25 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Statement = require('./statement'); -var KIND = 'include'; +const Expression = require("./expression"); +const KIND = "include"; /** * Defines system include call * @constructor Include - * @extends {Statement} + * @memberOf module:php-parser + * @extends {Expression} * @property {Node} target * @property {boolean} once * @property {boolean} require */ -var Include = Statement.extends(function Include(once, require, target, location) { - Statement.apply(this, [KIND, location]); - this.once = once; - this.require = require; - this.target = target; -}); - -module.exports = Include; +module.exports = Expression.extends( + KIND, + function Include(once, require, target, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.once = once; + this.require = require; + this.target = target; + }, +); diff --git a/src/ast/inline.js b/src/ast/inline.js index 3ce7f8ce3..822ab0698 100644 --- a/src/ast/inline.js +++ b/src/ast/inline.js @@ -1,19 +1,23 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Literal = require('./literal'); -var KIND = 'inline'; +const Literal = require("./literal"); +const KIND = "inline"; /** * Defines inline html output (treated as echo output) * @constructor Inline + * @memberOf module:php-parser * @extends {Literal} + * @property {string} value */ -var Inline = Literal.extends(function Inline(value, location) { - Literal.apply(this, [KIND, value, location]); -}); - -module.exports = Inline; +module.exports = Literal.extends( + KIND, + function Inline(value, raw, docs, location) { + Literal.apply(this, [KIND, value, raw, docs, location]); + }, +); diff --git a/src/ast/interface.js b/src/ast/interface.js index c218427c4..fcdd3f833 100644 --- a/src/ast/interface.js +++ b/src/ast/interface.js @@ -1,24 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Declaration = require('./declaration'); -var KIND = 'interface'; - +const Declaration = require("./declaration"); +const KIND = "interface"; /** * An interface definition * @constructor Interface + * @memberOf module:php-parser * @extends {Declaration} * @property {Identifier[]} extends * @property {Declaration[]} body + * @property {AttrGroup[]} attrGroups */ -var Interface = Declaration.extends(function Interface(name, ext, body, location) { - Declaration.apply(this, [KIND, name, location]); - this.extends = ext; - this.body = body; -}); - -module.exports = Interface; +module.exports = Declaration.extends( + KIND, + function Interface(name, ext, body, attrGroups, docs, location) { + Declaration.apply(this, [KIND, name, docs, location]); + this.extends = ext; + this.body = body; + this.attrGroups = attrGroups; + }, +); diff --git a/src/ast/intersectiontype.js b/src/ast/intersectiontype.js new file mode 100644 index 000000000..0a316d950 --- /dev/null +++ b/src/ast/intersectiontype.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Declaration = require("./declaration"); +const KIND = "intersectiontype"; + +/** + * A union of types + * @memberOf module:php-parser + * @constructor IntersectionType + * @extends {Declaration} + * @property {TypeReference[]} types + */ +module.exports = Declaration.extends( + KIND, + function IntersectionType(types, docs, location) { + Declaration.apply(this, [KIND, null, docs, location]); + this.types = types; + }, +); diff --git a/src/ast/isset.js b/src/ast/isset.js index 02ff7fb57..9ea1e2a5d 100644 --- a/src/ast/isset.js +++ b/src/ast/isset.js @@ -1,19 +1,23 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Sys = require('./sys'); -var KIND = 'isset'; +const Expression = require("./expression"); +const KIND = "isset"; /** * Defines an isset call * @constructor Isset - * @extends {Sys} + * @memberOf module:php-parser + * @extends {Expression} */ -var Isset = Sys.extends(function Isset(args, location) { - Sys.apply(this, [KIND, args, location]); -}); - -module.exports = Isset; +module.exports = Expression.extends( + KIND, + function Isset(variables, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.variables = variables; + }, +); diff --git a/src/ast/label.js b/src/ast/label.js index 5c86d2b78..c1e630413 100644 --- a/src/ast/label.js +++ b/src/ast/label.js @@ -1,21 +1,21 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Node = require('./node'); -var KIND = 'label'; + +const Statement = require("./statement"); +const KIND = "label"; /** * A label statement (referenced by goto) * @constructor Label - * @extends {Node} + * @memberOf module:php-parser + * @extends {Statement} * @property {String} name */ -var Label = Node.extends(function Label(name, location) { - Node.apply(this, [KIND, location]); +module.exports = Statement.extends(KIND, function Label(name, docs, location) { + Statement.apply(this, [KIND, docs, location]); this.name = name; }); - -module.exports = Label; diff --git a/src/ast/list.js b/src/ast/list.js index 82bc3523b..efe7ef5c4 100644 --- a/src/ast/list.js +++ b/src/ast/list.js @@ -1,19 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Sys = require('./sys'); -var KIND = 'list'; +const Expression = require("./expression"); +const KIND = "list"; /** * Defines list assignment * @constructor List - * @extends {Sys} + * @memberOf module:php-parser + * @extends {Expression} + * @property {boolean} shortForm + * @property {Entry[]} items */ -var List = Sys.extends(function List(args, location) { - Sys.apply(this, [KIND, args, location]); -}); - -module.exports = List; +module.exports = Expression.extends( + KIND, + function List(items, shortForm, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.items = items; + this.shortForm = shortForm; + }, +); diff --git a/src/ast/literal.js b/src/ast/literal.js index 5380a90c4..fcb849e06 100644 --- a/src/ast/literal.js +++ b/src/ast/literal.js @@ -1,21 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Expr = require('./expression'); -var KIND = 'literal'; +const Expression = require("./expression"); +const KIND = "literal"; /** * Defines an array structure * @constructor Literal + * @memberOf module:php-parser * @extends {Expression} - * @property {Node|string|number|boolean|null} value + * @property {string} raw + * @property {EncapsedPart[]|Node|string|number|boolean|null} value */ -var Literal = Expr.extends(function Literal(kind, value, location) { - Expr.apply(this, [kind || KIND, location]); - this.value = value; -}); - -module.exports = Literal; +module.exports = Expression.extends( + KIND, + function Literal(kind, value, raw, docs, location) { + Expression.apply(this, [kind || KIND, docs, location]); + this.value = value; + if (raw) { + this.raw = raw; + } + }, +); diff --git a/src/ast/location.js b/src/ast/location.js index f9ff0f435..65a975e89 100644 --- a/src/ast/location.js +++ b/src/ast/location.js @@ -1,17 +1,19 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; /** * Defines the location of the node (with it's source contents as string) * @constructor Location - * @property {String|null} source + * @memberOf module:php-parser + * @property {string|null} source * @property {Position} start * @property {Position} end */ -var Location = function(source, start, end) { +const Location = function (source, start, end) { this.source = source; this.start = start; this.end = end; diff --git a/src/ast/lookup.js b/src/ast/lookup.js index e8fc3e0e0..e0bf88a59 100644 --- a/src/ast/lookup.js +++ b/src/ast/lookup.js @@ -1,23 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Expr = require('./expression'); -var KIND = 'lookup'; +const Expr = require("./expression"); +const KIND = "lookup"; /** * Lookup on an offset in the specified object * @constructor Lookup + * @memberOf module:php-parser * @extends {Expression} * @property {Expression} what * @property {Expression} offset */ -var Lookup = Expr.extends(function Lookup(kind, what, offset, location) { - Expr.apply(this, [kind || KIND, location]); - this.what = what; - this.offset = offset; -}); - -module.exports = Lookup; +module.exports = Expr.extends( + KIND, + function Lookup(kind, what, offset, docs, location) { + Expr.apply(this, [kind || KIND, docs, location]); + this.what = what; + this.offset = offset; + }, +); diff --git a/src/ast/magic.js b/src/ast/magic.js index 8f0d4fddd..2ff5511cd 100644 --- a/src/ast/magic.js +++ b/src/ast/magic.js @@ -1,19 +1,22 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Literal = require('./literal'); -var KIND = 'magic'; +const Literal = require("./literal"); +const KIND = "magic"; /** * Defines magic constant * @constructor Magic + * @memberOf module:php-parser * @extends {Literal} */ -var Magic = Literal.extends(function Magic(value, location) { - Literal.apply(this, [KIND, value, location]); -}); - -module.exports = Magic; +module.exports = Literal.extends( + KIND, + function Magic(value, raw, docs, location) { + Literal.apply(this, [KIND, value, raw, docs, location]); + }, +); diff --git a/src/ast/match.js b/src/ast/match.js new file mode 100644 index 000000000..ab76fe85a --- /dev/null +++ b/src/ast/match.js @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Expression = require("./expression"); +const KIND = "match"; + +/** + * Defines a match expression + * @memberOf module:php-parser + * @constructor Match + * @extends {Expression} + * @property {Expression} cond Condition expression to match against + * @property {MatchArm[]} arms Arms for comparison + */ +module.exports = Expression.extends( + KIND, + function Match(cond, arms, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.cond = cond; + this.arms = arms; + }, +); diff --git a/src/ast/matcharm.js b/src/ast/matcharm.js new file mode 100644 index 000000000..b8aea6a2d --- /dev/null +++ b/src/ast/matcharm.js @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Expression = require("./expression"); +const KIND = "matcharm"; + +/** + * An array entry - see [Array](#array) + * @memberOf module:php-parser + * @constructor MatchArm + * @extends {Expression} + * @property {Expression[]|null} conds The match condition expression list - null indicates default arm + * @property {Expression} body The return value expression + */ +module.exports = Expression.extends( + KIND, + function MatchArm(conds, body, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.conds = conds; + this.body = body; + }, +); diff --git a/src/ast/method.js b/src/ast/method.js index 1c2530460..727db188a 100644 --- a/src/ast/method.js +++ b/src/ast/method.js @@ -1,24 +1,24 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var fn = require('./function'); -var KIND = 'method'; +const Function_ = require("./function"); +const KIND = "method"; /** * Defines a class/interface/trait method * @constructor Method + * @memberOf module:php-parser * @extends {Function} * @property {boolean} isAbstract * @property {boolean} isFinal * @property {boolean} isStatic * @property {string} visibility */ -var Method = fn.extends(function Method() { - fn.apply(this, arguments); +module.exports = Function_.extends(KIND, function Method() { + Function_.apply(this, arguments); this.kind = KIND; }); - -module.exports = Method; diff --git a/src/ast/name.js b/src/ast/name.js new file mode 100644 index 000000000..ae7ffcb21 --- /dev/null +++ b/src/ast/name.js @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Reference = require("./reference"); +const KIND = "name"; + +/** + * Defines a class reference node + * @constructor Name + * @memberOf module:php-parser + * @extends {Reference} + * @property {string} name + * @property {string} resolution + */ +const Name = Reference.extends( + KIND, + function Name(name, resolution, docs, location) { + Reference.apply(this, [KIND, docs, location]); + this.name = name.replace(/\\$/, ""); + this.resolution = resolution; + }, +); + +/** + * This is an identifier without a namespace separator, such as Foo + * @constant {String} Name#UNQUALIFIED_NAME + * @memberOf module:php-parser + */ +Name.UNQUALIFIED_NAME = "uqn"; +/** + * This is an identifier with a namespace separator, such as Foo\Bar + * @constant {String} Name#QUALIFIED_NAME + * @memberOf module:php-parser + */ +Name.QUALIFIED_NAME = "qn"; +/** + * This is an identifier with a namespace separator that begins with + * a namespace separator, such as \Foo\Bar. The namespace \Foo is also + * a fully qualified name. + * @constant {String} Name#FULL_QUALIFIED_NAME + * @memberOf module:php-parser + */ +Name.FULL_QUALIFIED_NAME = "fqn"; +/** + * This is an identifier starting with namespace, such as namespace\Foo\Bar. + * @constant {String} Name#RELATIVE_NAME + * @memberOf module:php-parser + */ +Name.RELATIVE_NAME = "rn"; + +module.exports = Name; diff --git a/src/ast/namedargument.js b/src/ast/namedargument.js new file mode 100644 index 000000000..63e35b2d0 --- /dev/null +++ b/src/ast/namedargument.js @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Expression = require("./expression"); +const KIND = "namedargument"; + +/** + * Named arguments. + * @memberOf module:php-parser + * @constructor namedargument + * @extends {Expression} + * @property {String} name + * @property {Expression} value + * @see https://www.php.net/manual/en/functions.arguments.php#functions.named-arguments + */ +module.exports = Expression.extends( + KIND, + function namedargument(name, value, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.name = name; + this.value = value; + }, +); diff --git a/src/ast/namespace.js b/src/ast/namespace.js index 3ca6bf6da..60b72086c 100644 --- a/src/ast/namespace.js +++ b/src/ast/namespace.js @@ -1,24 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Block = require('./block'); -var Identifier = require('./identifier'); -var KIND = 'namespace'; +const Block = require("./block"); +const KIND = "namespace"; /** * The main program node * @constructor Namespace + * @memberOf module:php-parser * @extends {Block} - * @property {String} name - * @property {Boolean} withBrackets + * @property {string} name + * @property {boolean} withBrackets */ -var Namespace = Block.extends(function Namespace(name, children, withBrackets, location) { - Block.apply(this, [KIND, children, location]); - this.name = name; - this.withBrackets = withBrackets || false; -}); - -module.exports = Namespace; +module.exports = Block.extends( + KIND, + function Namespace(name, children, withBrackets, docs, location) { + Block.apply(this, [KIND, children, docs, location]); + this.name = name; + this.withBrackets = withBrackets || false; + }, +); diff --git a/src/ast/new.js b/src/ast/new.js index 22a317af1..554a21aa3 100644 --- a/src/ast/new.js +++ b/src/ast/new.js @@ -1,24 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'new'; +const Expression = require("./expression"); +const KIND = "new"; /** * Creates a new instance of the specified class * @constructor New - * @extends {Statement} + * @memberOf module:php-parser + * @extends {Expression} * @property {Identifier|Variable|Class} what - * @property {Arguments[]} arguments + * @property {Variable[]} arguments */ -var New = Statement.extends(function New(what, args, location) { - Statement.apply(this, [KIND, location]); - this.what = what; - this.arguments = args; -}); - -module.exports = New; +module.exports = Expression.extends( + KIND, + function New(what, args, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.what = what; + this.arguments = args; + }, +); diff --git a/src/ast/node.js b/src/ast/node.js index 41b5b3ca7..111ae757d 100644 --- a/src/ast/node.js +++ b/src/ast/node.js @@ -1,31 +1,110 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; /** * A generic AST node * @constructor Node + * @memberOf module:php-parser * @property {Location|null} loc - * @property {String} kind + * @property {CommentBlock[]|Comment[]|null} leadingComments + * @property {CommentBlock[]|Comment[]|null} trailingComments + * @property {string} kind */ -var Node = function Node(kind, location) { +const Node = function Node(kind, docs, location) { this.kind = kind; - if(location) { + if (docs) { + this.leadingComments = docs; + } + if (location) { this.loc = location; } }; +/** + * Attach comments to current node + * @function Node#setTrailingComments + * @memberOf module:php-parser + * @param {*} docs + */ +Node.prototype.setTrailingComments = function (docs) { + this.trailingComments = docs; +}; + +/** + * Destroying an unused node + * @function Node#destroy + * @memberOf module:php-parser + */ +Node.prototype.destroy = function (node) { + if (!node) { + /* istanbul ignore next */ + throw new Error( + "Node already initialized, you must swap with another node", + ); + } + if (this.leadingComments) { + if (node.leadingComments) { + node.leadingComments = Array.concat( + this.leadingComments, + node.leadingComments, + ); + } else { + node.leadingComments = this.leadingComments; + } + } + if (this.trailingComments) { + if (node.trailingComments) { + node.trailingComments = Array.concat( + this.trailingComments, + node.trailingComments, + ); + } else { + node.trailingComments = this.trailingComments; + } + } + return node; +}; + +/** + * Includes current token position of the parser + * @function Node#includeToken + * @memberOf module:php-parser + * @param {*} parser + */ +Node.prototype.includeToken = function (parser) { + if (this.loc) { + if (this.loc.end) { + this.loc.end.line = parser.lexer.yylloc.last_line; + this.loc.end.column = parser.lexer.yylloc.last_column; + this.loc.end.offset = parser.lexer.offset; + } + if (parser.ast.withSource) { + this.loc.source = parser.lexer._input.substring( + this.loc.start.offset, + parser.lexer.offset, + ); + } + } + return this; +}; + /** * Helper for extending the Node class + * @function Node.extends + * @memberOf module:php-parser + * @param {string} type * @param {Function} constructor * @return {Function} */ -Node.extends = function(constructor) { +Node.extends = function (type, constructor) { constructor.prototype = Object.create(this.prototype); constructor.extends = this.extends; constructor.prototype.constructor = constructor; + constructor.kind = type; return constructor; }; diff --git a/src/ast/noop.js b/src/ast/noop.js new file mode 100644 index 000000000..f9d9e1ef0 --- /dev/null +++ b/src/ast/noop.js @@ -0,0 +1,20 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Node = require("./node"); +const KIND = "noop"; + +/** + * Ignore this node, it implies a no operation block, for example : + * [$foo, $bar, /* here a noop node * /] + * @constructor Noop + * @memberOf module:php-parser + * @extends {Node} + */ +module.exports = Node.extends(KIND, function Noop(docs, location) { + Node.apply(this, [KIND, docs, location]); +}); diff --git a/src/ast/nowdoc.js b/src/ast/nowdoc.js index a97bb30ae..726a3f954 100644 --- a/src/ast/nowdoc.js +++ b/src/ast/nowdoc.js @@ -1,22 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Literal = require('./literal'); -var KIND = 'nowdoc'; +const Literal = require("./literal"); +const KIND = "nowdoc"; /** * Defines a nowdoc string - * @constructor String + * @constructor NowDoc + * @memberOf module:php-parser * @extends {Literal} - * @property {String} label - + * @property {string} label + * @property {string} raw + * @property {string} value */ -var Nowdoc = Literal.extends(function Nowdoc(value, label, location) { - Literal.apply(this, [KIND, value, location]); - this.label = label; -}); - -module.exports = Nowdoc; +module.exports = Literal.extends( + KIND, + function Nowdoc(value, raw, label, docs, location) { + Literal.apply(this, [KIND, value, raw, docs, location]); + this.label = label; + }, +); diff --git a/src/ast/nullkeyword.js b/src/ast/nullkeyword.js new file mode 100644 index 000000000..cc6bf5f4d --- /dev/null +++ b/src/ast/nullkeyword.js @@ -0,0 +1,20 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Node = require("./node"); +const KIND = "nullkeyword"; + +/** + * Represents the null keyword + * @constructor NullKeyword + * @memberOf module:php-parser + * @extends {Node} + */ +module.exports = Node.extends(KIND, function NullKeyword(raw, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.raw = raw; +}); diff --git a/src/ast/nullsafepropertylookup.js b/src/ast/nullsafepropertylookup.js new file mode 100644 index 000000000..16003ec51 --- /dev/null +++ b/src/ast/nullsafepropertylookup.js @@ -0,0 +1,22 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Lookup = require("./lookup"); +const KIND = "nullsafepropertylookup"; + +/** + * Lookup to an object property + * @memberOf module:php-parser + * @constructor NullSafePropertyLookup + * @extends {Lookup} + */ +module.exports = Lookup.extends( + KIND, + function NullSafePropertyLookup(what, offset, docs, location) { + Lookup.apply(this, [KIND, what, offset, docs, location]); + }, +); diff --git a/src/ast/number.js b/src/ast/number.js index 25cde5cbc..0c1f9d4ee 100644 --- a/src/ast/number.js +++ b/src/ast/number.js @@ -1,19 +1,23 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Literal = require('./literal'); -var KIND = 'number'; +const Literal = require("./literal"); +const KIND = "number"; /** * Defines a numeric value * @constructor Number + * @memberOf module:php-parser * @extends {Literal} + * @property {number} value */ -var _Number = Literal.extends(function Number(value, location) { - Literal.apply(this, [KIND, value, location]); -}); - -module.exports = _Number; +module.exports = Literal.extends( + KIND, + function Number(value, raw, docs, location) { + Literal.apply(this, [KIND, value, raw, docs, location]); + }, +); diff --git a/src/ast/offsetlookup.js b/src/ast/offsetlookup.js index 198c96ee7..a9318855c 100644 --- a/src/ast/offsetlookup.js +++ b/src/ast/offsetlookup.js @@ -1,19 +1,22 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Lookup = require('./lookup'); -var KIND = 'offsetlookup'; + +const Lookup = require("./lookup"); +const KIND = "offsetlookup"; /** * Lookup on an offset in an array * @constructor OffsetLookup + * @memberOf module:php-parser * @extends {Lookup} */ -var OffsetLookup = Lookup.extends(function OffsetLookup(what, offset, location) { - Lookup.apply(this, [KIND, what, offset, location]); -}); - -module.exports = OffsetLookup; +module.exports = Lookup.extends( + KIND, + function OffsetLookup(what, offset, docs, location) { + Lookup.apply(this, [KIND, what, offset, docs, location]); + }, +); diff --git a/src/ast/operation.js b/src/ast/operation.js index ad5a007dd..6e3eda9ea 100644 --- a/src/ast/operation.js +++ b/src/ast/operation.js @@ -1,20 +1,19 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Expr = require('./expression'); -var KIND = 'operation'; +const Expr = require("./expression"); +const KIND = "operation"; /** * Defines binary operations * @constructor Operation + * @memberOf module:php-parser * @extends {Expression} */ -var Operation = Expr.extends(function Operation(kind, location) { - Expr.apply(this, [kind || KIND, location]); +module.exports = Expr.extends(KIND, function Operation(kind, docs, location) { + Expr.apply(this, [kind || KIND, docs, location]); }); - -module.exports = Operation; diff --git a/src/ast/parameter.js b/src/ast/parameter.js index d2b6222fc..7e417d528 100644 --- a/src/ast/parameter.js +++ b/src/ast/parameter.js @@ -1,29 +1,61 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Declaration = require('./declaration'); -var KIND = 'parameter'; +const Declaration = require("./declaration"); +const KIND = "parameter"; +/** + * @memberOf module:php-parser + * @typedef {1} MODIFIER_PUBLIC + **/ +/** + * @memberOf module:php-parser + * @typedef {2} MODIFIER_PROTECTED + **/ +/** + * @memberOf module:php-parser + * @typedef {4} MODIFIER_PRIVATE + **/ /** * Defines a function parameter * @constructor Parameter + * @memberOf module:php-parser * @extends {Declaration} * @property {Identifier|null} type * @property {Node|null} value * @property {boolean} byref * @property {boolean} variadic + * @property {boolean} readonly * @property {boolean} nullable + * @property {AttrGroup[]} attrGroups + * @property {MODIFIER_PUBLIC|MODIFIER_PROTECTED|MODIFIER_PRIVATE} flags */ -var Parameter = Declaration.extends(function Parameter(name, type, value, isRef, isVariadic, nullable, location) { - Declaration.apply(this, [KIND, name, location]); - this.value = value; - this.type = type; - this.byref = isRef; - this.variadic = isVariadic; - this.nullable = nullable; -}); - -module.exports = Parameter; +module.exports = Declaration.extends( + KIND, + function Parameter( + name, + type, + value, + isRef, + isVariadic, + readonly, + nullable, + flags, + docs, + location, + ) { + Declaration.apply(this, [KIND, name, docs, location]); + this.value = value; + this.type = type; + this.byref = isRef; + this.variadic = isVariadic; + this.readonly = readonly; + this.nullable = nullable; + this.flags = flags || 0; + this.attrGroups = []; + }, +); diff --git a/src/ast/parenthesis.js b/src/ast/parenthesis.js deleted file mode 100644 index db59fda29..000000000 --- a/src/ast/parenthesis.js +++ /dev/null @@ -1,22 +0,0 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ -"use strict"; - -var Operation = require('./operation'); -var KIND = 'parenthesis'; - -/** - * Parenthesis encapsulation `(... expr ...)` - * @constructor Parenthesis - * @extends {Operation} - * @property {Expression} inner - */ -var Parenthesis = Operation.extends(function Parenthesis(inner, location) { - Operation.apply(this, [KIND, location]); - this.inner = inner; -}); - -module.exports = Parenthesis; diff --git a/src/ast/parentreference.js b/src/ast/parentreference.js new file mode 100644 index 000000000..0ba489aa0 --- /dev/null +++ b/src/ast/parentreference.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Reference = require("./reference"); +const KIND = "parentreference"; + +/** + * Defines a class reference node + * @constructor ParentReference + * @memberOf module:php-parser + * @extends {Reference} + */ +const ParentReference = Reference.extends( + KIND, + function ParentReference(raw, docs, location) { + Reference.apply(this, [KIND, docs, location]); + this.raw = raw; + }, +); +module.exports = ParentReference; diff --git a/src/ast/position.js b/src/ast/position.js index 04b87b4d9..6e4f123c4 100644 --- a/src/ast/position.js +++ b/src/ast/position.js @@ -1,17 +1,19 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; /** * Each Position object consists of a line number (1-indexed) and a column number (0-indexed): * @constructor Position - * @property {Number} line - * @property {Number} column - * @property {Number} offset + * @memberOf module:php-parser + * @property {number} line + * @property {number} column + * @property {number} offset */ -var Position = function(line, column, offset) { +const Position = function (line, column, offset) { this.line = line; this.column = column; this.offset = offset; diff --git a/src/ast/post.js b/src/ast/post.js index 1ec35fc62..56b48b937 100644 --- a/src/ast/post.js +++ b/src/ast/post.js @@ -1,24 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Operation = require('./operation'); -var KIND = 'post'; +const Operation = require("./operation"); +const KIND = "post"; /** * Defines a post operation `$i++` or `$i--` * @constructor Post + * @memberOf module:php-parser * @extends {Operation} * @property {String} type * @property {Variable} what */ -var Post = Operation.extends(function Post(type, what, location) { - Operation.apply(this, [KIND, location]); - this.type = type; - this.what = what; -}); - -module.exports = Post; +module.exports = Operation.extends( + KIND, + function Post(type, what, docs, location) { + Operation.apply(this, [KIND, docs, location]); + this.type = type; + this.what = what; + }, +); diff --git a/src/ast/pre.js b/src/ast/pre.js index e5454a06a..58b84a710 100644 --- a/src/ast/pre.js +++ b/src/ast/pre.js @@ -1,24 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Operation = require('./operation'); -var KIND = 'pre'; +const Operation = require("./operation"); +const KIND = "pre"; /** * Defines a pre operation `++$i` or `--$i` * @constructor Pre + * @memberOf module:php-parser * @extends {Operation} * @property {String} type * @property {Variable} what */ -var Pre = Operation.extends(function Pre(type, what, location) { - Operation.apply(this, [KIND, location]); - this.type = type; - this.what = what; -}); - -module.exports = Pre; +module.exports = Operation.extends( + KIND, + function Pre(type, what, docs, location) { + Operation.apply(this, [KIND, docs, location]); + this.type = type; + this.what = what; + }, +); diff --git a/src/ast/print.js b/src/ast/print.js index 3768808bc..3455263c9 100644 --- a/src/ast/print.js +++ b/src/ast/print.js @@ -1,19 +1,23 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Sys = require('./sys'); -var KIND = 'print'; +const Expression = require("./expression"); +const KIND = "print"; /** * Outputs * @constructor Print - * @extends {Sys} + * @memberOf module:php-parser + * @extends {Expression} */ -var Print = Sys.extends(function Print(args, location) { - Sys.apply(this, [KIND, args, location]); -}); - -module.exports = Print; +module.exports = Expression.extends( + KIND, + function Print(expression, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.expression = expression; + }, +); diff --git a/src/ast/program.js b/src/ast/program.js index bec2e187a..5ea3d764f 100644 --- a/src/ast/program.js +++ b/src/ast/program.js @@ -1,21 +1,32 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Block = require('./block'); -var KIND = 'program'; +const Block = require("./block"); +const KIND = "program"; /** * The main program node * @constructor Program + * @memberOf module:php-parser * @extends {Block} * @property {Error[]} errors + * @property {Comment[]|null} comments + * @property {String[]|null} tokens */ -var Program = Block.extends(function Program(children, errors, location) { - Block.apply(this, [KIND, children, location]); - this.errors = errors; -}); - -module.exports = Program; +module.exports = Block.extends( + KIND, + function Program(children, errors, comments, tokens, docs, location) { + Block.apply(this, [KIND, children, docs, location]); + this.errors = errors; + if (comments) { + this.comments = comments; + } + if (tokens) { + this.tokens = tokens; + } + }, +); diff --git a/src/ast/property.js b/src/ast/property.js index 3136b9883..ad01986ce 100644 --- a/src/ast/property.js +++ b/src/ast/property.js @@ -1,25 +1,43 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Declaration = require('./declaration'); -var KIND = 'property'; +const Statement = require("./statement"); +const KIND = "property"; /** * Defines a class property * @constructor Property - * @extends {Declaration} - * @property {boolean} isFinal - * @property {boolean} isStatic - * @property {string} visibility + * @memberOf module:php-parser + * @extends {Statement} + * @property {string} name * @property {Node|null} value + * @property {boolean} readonly + * @property {boolean} nullable + * @property {Identifier|Array|null} type + * @property {AttrGroup[]} attrGroups */ -var Property = Declaration.extends(function Property(name, value, flags, location) { - Declaration.apply(this, [KIND, name, location]); - this.value = value; - this.parseFlags(flags); -}); - -module.exports = Property; +module.exports = Statement.extends( + KIND, + function Property( + name, + value, + readonly, + nullable, + type, + attrGroups, + docs, + location, + ) { + Statement.apply(this, [KIND, docs, location]); + this.name = name; + this.value = value; + this.readonly = readonly; + this.nullable = nullable; + this.type = type; + this.attrGroups = attrGroups; + }, +); diff --git a/src/ast/propertylookup.js b/src/ast/propertylookup.js index fe38314d9..ef2b14a80 100644 --- a/src/ast/propertylookup.js +++ b/src/ast/propertylookup.js @@ -1,19 +1,22 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Lookup = require('./lookup'); -var KIND = 'propertylookup'; + +const Lookup = require("./lookup"); +const KIND = "propertylookup"; /** * Lookup to an object property + * @memberOf module:php-parser * @constructor PropertyLookup * @extends {Lookup} */ -var PropertyLookup = Lookup.extends(function PropertyLookup(what, offset, location) { - Lookup.apply(this, [KIND, what, offset, location]); -}); - -module.exports = PropertyLookup; +module.exports = Lookup.extends( + KIND, + function PropertyLookup(what, offset, docs, location) { + Lookup.apply(this, [KIND, what, offset, docs, location]); + }, +); diff --git a/src/ast/propertystatement.js b/src/ast/propertystatement.js new file mode 100644 index 000000000..271c8e6a8 --- /dev/null +++ b/src/ast/propertystatement.js @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Statement = require("./statement"); +const KIND = "propertystatement"; + +const IS_UNDEFINED = ""; +const IS_PUBLIC = "public"; +const IS_PROTECTED = "protected"; +const IS_PRIVATE = "private"; + +/** + * Declares a properties into the current scope + * @constructor PropertyStatement + * @memberOf module:php-parser + * @extends {Statement} + * @property {Property[]} properties + * @property {string|null} visibility + * @property {boolean} isStatic + */ +const PropertyStatement = Statement.extends( + KIND, + function PropertyStatement(kind, properties, flags, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.properties = properties; + this.parseFlags(flags); + }, +); + +/** + * Generic flags parser + * @function PropertyStatement#parseFlags + * @memberOf module:php-parser + * @param {Array} flags + * @return {void} + */ +PropertyStatement.prototype.parseFlags = function (flags) { + if (flags[0] === -1) { + this.visibility = IS_UNDEFINED; + } else if (flags[0] === null) { + this.visibility = null; + } else if (flags[0] === 0) { + this.visibility = IS_PUBLIC; + } else if (flags[0] === 1) { + this.visibility = IS_PROTECTED; + } else if (flags[0] === 2) { + this.visibility = IS_PRIVATE; + } + + this.isStatic = flags[1] === 1; +}; + +module.exports = PropertyStatement; diff --git a/src/ast/reference.js b/src/ast/reference.js new file mode 100644 index 000000000..e000937ad --- /dev/null +++ b/src/ast/reference.js @@ -0,0 +1,21 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Node = require("./node"); +const KIND = "reference"; + +/** + * Defines a reference node + * @constructor Reference + * @memberOf module:php-parser + * @extends {Node} + */ +const Reference = Node.extends(KIND, function Reference(kind, docs, location) { + Node.apply(this, [kind || KIND, docs, location]); +}); + +module.exports = Reference; diff --git a/src/ast/retif.js b/src/ast/retif.js index dafcf4052..70a044f60 100644 --- a/src/ast/retif.js +++ b/src/ast/retif.js @@ -1,26 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'retif'; +const Expression = require("./expression"); +const KIND = "retif"; /** * Defines a short if statement that returns a value * @constructor RetIf - * @extends {Statement} + * @memberOf module:php-parser + * @extends {Expression} * @property {Expression} test * @property {Expression} trueExpr * @property {Expression} falseExpr */ -var RetIf = Statement.extends(function RetIf(test, trueExpr, falseExpr, location) { - Statement.apply(this, [KIND, location]); - this.test = test; - this.trueExpr = trueExpr; - this.falseExpr = falseExpr; -}); - -module.exports = RetIf; +module.exports = Expression.extends( + KIND, + function RetIf(test, trueExpr, falseExpr, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.test = test; + this.trueExpr = trueExpr; + this.falseExpr = falseExpr; + }, +); diff --git a/src/ast/return.js b/src/ast/return.js index cc456fda8..c7c049baa 100644 --- a/src/ast/return.js +++ b/src/ast/return.js @@ -1,21 +1,21 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Node = require('./node'); -var KIND = 'return'; + +const Statement = require("./statement"); +const KIND = "return"; /** * A continue statement * @constructor Return - * @extends {Node} + * @memberOf module:php-parser + * @extends {Statement} * @property {Expression|null} expr */ -var Return = Node.extends(function Return(expr, location) { - Node.apply(this, [KIND, location]); +module.exports = Statement.extends(KIND, function Return(expr, docs, location) { + Statement.apply(this, [KIND, docs, location]); this.expr = expr; }); - -module.exports = Return; diff --git a/src/ast/selfreference.js b/src/ast/selfreference.js new file mode 100644 index 000000000..0259e9752 --- /dev/null +++ b/src/ast/selfreference.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Reference = require("./reference"); +const KIND = "selfreference"; + +/** + * Defines a class reference node + * @constructor SelfReference + * @memberOf module:php-parser + * @extends {Reference} + */ +const SelfReference = Reference.extends( + KIND, + function SelfReference(raw, docs, location) { + Reference.apply(this, [KIND, docs, location]); + this.raw = raw; + }, +); +module.exports = SelfReference; diff --git a/src/ast/silent.js b/src/ast/silent.js index 6df0c3384..8bf60defc 100644 --- a/src/ast/silent.js +++ b/src/ast/silent.js @@ -1,22 +1,24 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'silent'; +const Expression = require("./expression"); +const KIND = "silent"; /** * Avoids to show/log warnings & notices from the inner expression * @constructor Silent - * @extends {Statement} + * @memberOf module:php-parser + * @extends {Expression} * @property {Expression} expr */ -var Silent = Statement.extends(function Silent(expr, location) { - Statement.apply(this, [KIND, location]); - this.expr = expr; -}); - -module.exports = Silent; +module.exports = Expression.extends( + KIND, + function Silent(expr, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.expr = expr; + }, +); diff --git a/src/ast/statement.js b/src/ast/statement.js index 6afaf6ff3..6f25bd8ee 100644 --- a/src/ast/statement.js +++ b/src/ast/statement.js @@ -1,19 +1,19 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Node = require('./node'); -var KIND = 'statement'; +const Node = require("./node"); +const KIND = "statement"; /** * Any statement. * @constructor Statement + * @memberOf module:php-parser * @extends {Node} */ -var Statement = Node.extends(function Statement(kind, location) { - Node.apply(this, [kind || KIND, location]); +module.exports = Node.extends(KIND, function Statement(kind, docs, location) { + Node.apply(this, [kind || KIND, docs, location]); }); - -module.exports = Statement; diff --git a/src/ast/static.js b/src/ast/static.js index be86eac8c..33f00145a 100644 --- a/src/ast/static.js +++ b/src/ast/static.js @@ -1,21 +1,24 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'static'; + +const Statement = require("./statement"); +const KIND = "static"; /** * Declares a static variable into the current scope * @constructor Static + * @memberOf module:php-parser * @extends {Statement} - * @property {Variable[]|Assign[]} items + * @property {StaticVariable[]} variables */ -var Static = Statement.extends(function Static(items, location) { - Statement.apply(this, [KIND, location]); - this.items = items; -}); - -module.exports = Static; +module.exports = Statement.extends( + KIND, + function Static(variables, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.variables = variables; + }, +); diff --git a/src/ast/staticlookup.js b/src/ast/staticlookup.js index 4c40ea650..5bbd2d594 100644 --- a/src/ast/staticlookup.js +++ b/src/ast/staticlookup.js @@ -1,19 +1,22 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Lookup = require('./lookup'); -var KIND = 'staticlookup'; + +const Lookup = require("./lookup"); +const KIND = "staticlookup"; /** * Lookup to a static property * @constructor StaticLookup + * @memberOf module:php-parser * @extends {Lookup} */ -var StaticLookup = Lookup.extends(function StaticLookup(what, offset, location) { - Lookup.apply(this, [KIND, what, offset, location]); -}); - -module.exports = StaticLookup; +module.exports = Lookup.extends( + KIND, + function StaticLookup(what, offset, docs, location) { + Lookup.apply(this, [KIND, what, offset, docs, location]); + }, +); diff --git a/src/ast/staticreference.js b/src/ast/staticreference.js new file mode 100644 index 000000000..c3b0755f2 --- /dev/null +++ b/src/ast/staticreference.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Reference = require("./reference"); +const KIND = "staticreference"; + +/** + * Defines a class reference node + * @constructor StaticReference + * @memberOf module:php-parser + * @extends {Reference} + */ +const StaticReference = Reference.extends( + KIND, + function StaticReference(raw, docs, location) { + Reference.apply(this, [KIND, docs, location]); + this.raw = raw; + }, +); +module.exports = StaticReference; diff --git a/src/ast/staticvariable.js b/src/ast/staticvariable.js new file mode 100644 index 000000000..2388c4f24 --- /dev/null +++ b/src/ast/staticvariable.js @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Node = require("./node"); +const KIND = "staticvariable"; + +/** + * Defines a constant + * @constructor StaticVariable + * @memberOf module:php-parser + * @extends {Node} + * @property {Variable} variable + * @property {Node|string|number|boolean|null} defaultValue + */ +module.exports = Node.extends( + KIND, + function StaticVariable(variable, defaultValue, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.variable = variable; + this.defaultValue = defaultValue; + }, +); diff --git a/src/ast/string.js b/src/ast/string.js index 290a9127c..c2c7423a1 100644 --- a/src/ast/string.js +++ b/src/ast/string.js @@ -1,22 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Literal = require('./literal'); -var KIND = 'string'; +const Literal = require("./literal"); +const KIND = "string"; /** - * Defines a string (simple ou double quoted) - chars are already escaped + * Defines a string (simple or double quoted) - chars are already escaped * @constructor String + * @memberOf module:php-parser * @extends {Literal} + * @property {boolean} unicode * @property {boolean} isDoubleQuote * @see {Encapsed} + * @property {string} value */ -var String = Literal.extends(function String(isDoubleQuote, value, location) { - Literal.apply(this, [KIND, value, location]); - this.isDoubleQuote = isDoubleQuote; -}); - -module.exports = String; +module.exports = Literal.extends( + KIND, + function String(isDoubleQuote, value, unicode, raw, docs, location) { + Literal.apply(this, [KIND, value, raw, docs, location]); + this.unicode = unicode; + this.isDoubleQuote = isDoubleQuote; + }, +); diff --git a/src/ast/switch.js b/src/ast/switch.js index 2126d9d3c..6f48d2142 100644 --- a/src/ast/switch.js +++ b/src/ast/switch.js @@ -1,26 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'switch'; +const Statement = require("./statement"); +const KIND = "switch"; /** * Defines a switch statement * @constructor Switch + * @memberOf module:php-parser * @extends {Statement} * @property {Expression} test * @property {Block} body * @property {boolean} shortForm */ -var Switch = Statement.extends(function Switch(test, body, shortForm, location) { - Statement.apply(this, [KIND, location]); - this.test = test; - this.body = body; - this.shortForm = shortForm; -}); - -module.exports = Switch; +module.exports = Statement.extends( + KIND, + function Switch(test, body, shortForm, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.test = test; + this.body = body; + this.shortForm = shortForm; + }, +); diff --git a/src/ast/sys.js b/src/ast/sys.js deleted file mode 100644 index 1d23b6724..000000000 --- a/src/ast/sys.js +++ /dev/null @@ -1,21 +0,0 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) - * @authors https://github.com/glayzzle/php-parser/graphs/contributors - * @url http://glayzzle.com - */ - -var Statement = require('./statement'); -var KIND = 'sys'; - -/** - * Defines system based call - * @constructor Sys - * @extends {Statement} - * @property {Node[]} arguments - */ -var Sys = Statement.extends(function Sys(kind, args, location) { - Statement.apply(this, [kind || KIND, location]); - this.arguments = args; -}); - -module.exports = Sys; diff --git a/src/ast/throw.js b/src/ast/throw.js index 0982924c1..36c51f88e 100644 --- a/src/ast/throw.js +++ b/src/ast/throw.js @@ -1,22 +1,21 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'throw'; +const Statement = require("./statement"); +const KIND = "throw"; /** * Defines a throw statement * @constructor Throw + * @memberOf module:php-parser * @extends {Statement} * @property {Expression} what */ -var Throw = Statement.extends(function Throw(what, location) { - Statement.apply(this, [KIND, location]); +module.exports = Statement.extends(KIND, function Throw(what, docs, location) { + Statement.apply(this, [KIND, docs, location]); this.what = what; }); - -module.exports = Throw; diff --git a/src/ast/trait.js b/src/ast/trait.js index ae2a5a18a..62151e911 100644 --- a/src/ast/trait.js +++ b/src/ast/trait.js @@ -1,26 +1,24 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Declaration = require('./declaration'); -var KIND = 'trait'; - +const Declaration = require("./declaration"); +const KIND = "trait"; /** * A trait definition * @constructor Trait + * @memberOf module:php-parser * @extends {Declaration} - * @property {Identifier|null} extends - * @property {Identifier[]} implements * @property {Declaration[]} body */ -var Trait = Declaration.extends(function Trait(name, ext, impl, body, location) { - Declaration.apply(this, [KIND, name, location]); - this.extends = ext; - this.implements = impl; - this.body = body; -}); - -module.exports = Trait; +module.exports = Declaration.extends( + KIND, + function Trait(name, body, docs, location) { + Declaration.apply(this, [KIND, name, docs, location]); + this.body = body; + }, +); diff --git a/src/ast/traitalias.js b/src/ast/traitalias.js index fd28214d5..d6a9ecdf0 100644 --- a/src/ast/traitalias.js +++ b/src/ast/traitalias.js @@ -1,41 +1,44 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Node = require('./node'); -var KIND = 'traitalias'; +const Node = require("./node"); +const KIND = "traitalias"; -var IS_PUBLIC = 'public'; -var IS_PROTECTED = 'protected'; -var IS_PRIVATE = 'private'; +const IS_UNDEFINED = ""; +const IS_PUBLIC = "public"; +const IS_PROTECTED = "protected"; +const IS_PRIVATE = "private"; /** * Defines a trait alias * @constructor TraitAlias + * @memberOf module:php-parser * @extends {Node} * @property {Identifier|null} trait - * @property {string} method - * @property {string|null} as + * @property {Identifier} method + * @property {Identifier|null} as * @property {string|null} visibility */ -var TraitAlias = Node.extends(function TraitAlias(trait, method, as, flags, location) { - Node.apply(this, [KIND, location]); - this.trait = trait; - this.method = method; - this.as = as; - if (flags) { - if (flags[0] === 0) { - this.visibility = IS_PUBLIC; - } else if (flags[0] === 1) { - this.visibility = IS_PROTECTED; - } else { - this.visibility = IS_PRIVATE; +module.exports = Node.extends( + KIND, + function TraitAlias(trait, method, as, flags, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.trait = trait; + this.method = method; + this.as = as; + this.visibility = IS_UNDEFINED; + if (flags) { + if (flags[0] === 0) { + this.visibility = IS_PUBLIC; + } else if (flags[0] === 1) { + this.visibility = IS_PROTECTED; + } else if (flags[0] === 2) { + this.visibility = IS_PRIVATE; + } } - } else { - this.visibility = null; - } -}); - -module.exports = TraitAlias; + }, +); diff --git a/src/ast/traitprecedence.js b/src/ast/traitprecedence.js index a5bd405c9..99ad43940 100644 --- a/src/ast/traitprecedence.js +++ b/src/ast/traitprecedence.js @@ -1,25 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Node = require('./node'); -var KIND = 'traitprecedence'; +const Node = require("./node"); +const KIND = "traitprecedence"; /** * Defines a trait alias * @constructor TraitPrecedence + * @memberOf module:php-parser * @extends {Node} * @property {Identifier|null} trait - * @property {string} method + * @property {Identifier} method * @property {Identifier[]} instead */ -var TraitPrecedence = Node.extends(function TraitPrecedence(trait, method, instead, location) { - Node.apply(this, [KIND, location]); - this.trait = trait; - this.method = method; - this.instead = instead; -}); - -module.exports = TraitPrecedence; +module.exports = Node.extends( + KIND, + function TraitPrecedence(trait, method, instead, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.trait = trait; + this.method = method; + this.instead = instead; + }, +); diff --git a/src/ast/traituse.js b/src/ast/traituse.js index d30610764..fc163dc57 100644 --- a/src/ast/traituse.js +++ b/src/ast/traituse.js @@ -1,23 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Node = require('./node'); -var KIND = 'traituse'; +const Node = require("./node"); +const KIND = "traituse"; /** * Defines a trait usage * @constructor TraitUse + * @memberOf module:php-parser * @extends {Node} * @property {Identifier[]} traits * @property {Node[]|null} adaptations */ -var TraitUse = Node.extends(function TraitUse(traits, adaptations, location) { - Node.apply(this, [KIND, location]); - this.traits = traits; - this.adaptations = adaptations; -}); - -module.exports = TraitUse; +module.exports = Node.extends( + KIND, + function TraitUse(traits, adaptations, docs, location) { + Node.apply(this, [KIND, docs, location]); + this.traits = traits; + this.adaptations = adaptations; + }, +); diff --git a/src/ast/try.js b/src/ast/try.js index dc4dd0e0c..9a97f0728 100644 --- a/src/ast/try.js +++ b/src/ast/try.js @@ -1,26 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'try'; +const Statement = require("./statement"); +const KIND = "try"; /** * Defines a try statement * @constructor Try + * @memberOf module:php-parser * @extends {Statement} * @property {Block} body * @property {Catch[]} catches - * @property {Block} allways + * @property {Block} always */ -var Try = Statement.extends(function Try(body, catches, always, location) { - Statement.apply(this, [KIND, location]); - this.body = body; - this.catches = catches; - this.always = always; -}); - -module.exports = Try; +module.exports = Statement.extends( + KIND, + function Try(body, catches, always, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.body = body; + this.catches = catches; + this.always = always; + }, +); diff --git a/src/ast/typereference.js b/src/ast/typereference.js new file mode 100644 index 000000000..944f74665 --- /dev/null +++ b/src/ast/typereference.js @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Reference = require("./reference"); +const KIND = "typereference"; + +/** + * Defines a class reference node + * @constructor TypeReference + * @memberOf module:php-parser + * @extends {Reference} + * @property {string} name + */ +const TypeReference = Reference.extends( + KIND, + function TypeReference(name, raw, docs, location) { + Reference.apply(this, [KIND, docs, location]); + this.name = name; + this.raw = raw; + }, +); + +TypeReference.types = [ + "int", + "float", + "string", + "bool", + "object", + "array", + "callable", + "iterable", + "void", + "static", +]; + +module.exports = TypeReference; diff --git a/src/ast/unary.js b/src/ast/unary.js index bfd8e3422..7d086c0a0 100644 --- a/src/ast/unary.js +++ b/src/ast/unary.js @@ -1,24 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Operation = require('./operation'); -var KIND = 'unary'; +const Operation = require("./operation"); +const KIND = "unary"; /** * Unary operations * @constructor Unary + * @memberOf module:php-parser * @extends {Operation} - * @property {String} type + * @property {string} type * @property {Expression} what */ -var Unary = Operation.extends(function Unary(type, what, location) { - Operation.apply(this, [KIND, location]); - this.type = type; - this.what = what; -}); - -module.exports = Unary; +module.exports = Operation.extends( + KIND, + function Unary(type, what, docs, location) { + Operation.apply(this, [KIND, docs, location]); + this.type = type; + this.what = what; + }, +); diff --git a/src/ast/uniontype.js b/src/ast/uniontype.js new file mode 100644 index 000000000..e4d2bc318 --- /dev/null +++ b/src/ast/uniontype.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Declaration = require("./declaration"); +const KIND = "uniontype"; + +/** + * A union of types + * @memberOf module:php-parser + * @constructor UnionType + * @extends {Declaration} + * @property {TypeReference[]} types + */ +module.exports = Declaration.extends( + KIND, + function UnionType(types, docs, location) { + Declaration.apply(this, [KIND, null, docs, location]); + this.types = types; + }, +); diff --git a/src/ast/unset.js b/src/ast/unset.js index 6e60e58ca..36f110cc8 100644 --- a/src/ast/unset.js +++ b/src/ast/unset.js @@ -1,19 +1,23 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var Sys = require('./sys'); -var KIND = 'unset'; +const Statement = require("./statement"); +const KIND = "unset"; /** * Deletes references to a list of variables * @constructor Unset - * @extends {Sys} + * @memberOf module:php-parser + * @extends {Statement} */ -var Unset = Sys.extends(function Unset(args, location) { - Sys.apply(this, [KIND, args, location]); -}); - -module.exports = Unset; +module.exports = Statement.extends( + KIND, + function Unset(variables, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.variables = variables; + }, +); diff --git a/src/ast/usegroup.js b/src/ast/usegroup.js index 20c8406da..d00cfd74e 100644 --- a/src/ast/usegroup.js +++ b/src/ast/usegroup.js @@ -1,27 +1,30 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'usegroup'; + +const Statement = require("./statement"); +const KIND = "usegroup"; /** * Defines a use statement (with a list of use items) * @constructor UseGroup + * @memberOf module:php-parser * @extends {Statement} - * @property {String|null} name - * @property {String|null} type - Possible value : function, const + * @property {string|null} name + * @property {string|null} type - Possible value : function, const * @property {UseItem[]} item * @see {Namespace} * @see http://php.net/manual/en/language.namespaces.importing.php */ -var UseGroup = Statement.extends(function UseGroup(name, type, items, location) { - Statement.apply(this, [KIND, location]); - this.name = name; - this.type = type; - this.items = items; -}); - -module.exports = UseGroup; +module.exports = Statement.extends( + KIND, + function UseGroup(name, type, items, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.name = name; + this.type = type; + this.items = items; + }, +); diff --git a/src/ast/useitem.js b/src/ast/useitem.js index 50d514c9f..17af88c4f 100644 --- a/src/ast/useitem.js +++ b/src/ast/useitem.js @@ -1,40 +1,45 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'useitem'; + +const Statement = require("./statement"); +const KIND = "useitem"; /** * Defines a use statement (from namespace) * @constructor UseItem + * @memberOf module:php-parser * @extends {Statement} - * @property {String} name - * @property {String|null} type - Possible value : function, const - * @property {String|null} alias + * @property {string} name + * @property {string|null} type - Possible value : function, const + * @property {Identifier|null} alias * @see {Namespace} * @see http://php.net/manual/en/language.namespaces.importing.php */ -var UseItem = Statement.extends(function UseItem(name, alias, type, location) { - Statement.apply(this, [KIND, location]); - this.name = name; - this.alias = alias; - this.type = type; -}); - +const UseItem = Statement.extends( + KIND, + function UseItem(name, alias, type, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.name = name; + this.alias = alias; + this.type = type; + }, +); /** * Importing a constant - * @constant {String} TYPE_CONST + * @constant {string} UseItem#TYPE_CONST + * @memberOf module:php-parser */ -UseItem.TYPE_CONST = 'const'; +UseItem.TYPE_CONST = "const"; /** * Importing a function - * @constant {String} TYPE_FUNC + * @constant {string} UseItem#TYPE_FUNC + * @memberOf module:php-parser */ -UseItem.TYPE_FUNCTION = 'function'; - +UseItem.TYPE_FUNCTION = "function"; module.exports = UseItem; diff --git a/src/ast/variable.js b/src/ast/variable.js index e2e1a39e4..cd6609036 100644 --- a/src/ast/variable.js +++ b/src/ast/variable.js @@ -1,36 +1,36 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Expr = require('./expression'); -var KIND = 'variable'; + +const Expression = require("./expression"); +const KIND = "variable"; /** * Any expression node. Since the left-hand side of an assignment may * be any expression in general, an expression can also be a pattern. * @constructor Variable + * @memberOf module:php-parser * @extends {Expression} * @example * // PHP code : - * &$foo + * $foo * // AST output * { * "kind": "variable", * "name": "foo", - * "byref": true, * "curly": false * } - * @property {String|Node} name The variable name (can be a complex expression when the name is resolved dynamically) - * @property {boolean} byref Indicate if the variable reference is used, ex `&$foo` + * @property {string|Node} name The variable name (can be a complex expression when the name is resolved dynamically) * @property {boolean} curly Indicate if the name is defined between curlies, ex `${foo}` */ -var Variable = Expr.extends(function Variable(name, byref, curly, location) { - Expr.apply(this, [KIND, location]); - this.name = name; - this.byref = byref || false; - this.curly = curly || false; -}); - -module.exports = Variable; +module.exports = Expression.extends( + KIND, + function Variable(name, curly, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.name = name; + this.curly = curly || false; + }, +); diff --git a/src/ast/variadic.js b/src/ast/variadic.js index b76c39fae..c9783ae3f 100644 --- a/src/ast/variadic.js +++ b/src/ast/variadic.js @@ -1,22 +1,25 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Expr = require('./expression'); -var KIND = 'variadic'; + +const Expression = require("./expression"); +const KIND = "variadic"; /** * Introduce a list of items into the arguments of the call * @constructor Variadic + * @memberOf module:php-parser * @extends {Expression} * @property {Array|Expression} what * @see https://wiki.php.net/rfc/argument_unpacking */ -var Variadic = Expr.extends(function Variadic(what, location) { - Expr.apply(this, [KIND, location]); - this.what = what; -}); - -module.exports = Variadic; +module.exports = Expression.extends( + KIND, + function variadic(what, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.what = what; + }, +); diff --git a/src/ast/variadicplaceholder.js b/src/ast/variadicplaceholder.js new file mode 100644 index 000000000..4e1fe657d --- /dev/null +++ b/src/ast/variadicplaceholder.js @@ -0,0 +1,24 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +const Node = require("./node"); +const KIND = "variadicplaceholder"; + +/** + * Defines a variadic placeholder (the ellipsis in PHP 8.1+'s first-class callable syntax) + * @constructor VariadicPlaceholder + * @memberOf module:php-parser + * @extends {Node} + * @see {Namespace} + * @see http://php.net/manual/en/language.namespaces.importing.php + */ +module.exports = Node.extends( + KIND, + function VariadicPlaceholder(docs, location) { + Node.apply(this, [KIND, docs, location]); + }, +); diff --git a/src/ast/while.js b/src/ast/while.js index 9ff909594..d92972717 100644 --- a/src/ast/while.js +++ b/src/ast/while.js @@ -1,26 +1,28 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Statement = require('./statement'); -var KIND = 'while'; +const Statement = require("./statement"); +const KIND = "while"; /** * Defines a while statement * @constructor While + * @memberOf module:php-parser * @extends {Statement} * @property {Expression} test - * @property {Statement} body + * @property {Block | null} body * @property {boolean} shortForm */ -var While = Statement.extends(function While(test, body, shortForm, location) { - Statement.apply(this, [KIND, location]); - this.test = test; - this.body = body; - this.shortForm = shortForm; -}); - -module.exports = While; +module.exports = Statement.extends( + KIND, + function While(test, body, shortForm, docs, location) { + Statement.apply(this, [KIND, docs, location]); + this.test = test; + this.body = body; + this.shortForm = shortForm; + }, +); diff --git a/src/ast/yield.js b/src/ast/yield.js index 035366e15..4cd92e54c 100644 --- a/src/ast/yield.js +++ b/src/ast/yield.js @@ -1,25 +1,27 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Expression = require('./expression'); -var KIND = 'yield'; +const Expression = require("./expression"); +const KIND = "yield"; /** * Defines a yield generator statement * @constructor Yield + * @memberOf module:php-parser * @extends {Expression} - * @property {Expression|Null} value - * @property {Expression|Null} key + * @property {Expression|null} value + * @property {Expression|null} key * @see http://php.net/manual/en/language.generators.syntax.php */ -var Yield = Expression.extends(function Yield(value, key, location) { - Expression.apply(this, [KIND, location]); - this.value = value; - this.key = key; -}); - -module.exports = Yield; +module.exports = Expression.extends( + KIND, + function Yield(value, key, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.value = value; + this.key = key; + }, +); diff --git a/src/ast/yieldfrom.js b/src/ast/yieldfrom.js index f3a5de37e..11cf8df97 100644 --- a/src/ast/yieldfrom.js +++ b/src/ast/yieldfrom.js @@ -1,23 +1,25 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; -var Expression = require('./expression'); -var KIND = 'yieldfrom'; +const Expression = require("./expression"); +const KIND = "yieldfrom"; /** * Defines a yield from generator statement * @constructor YieldFrom + * @memberOf module:php-parser * @extends {Expression} * @property {Expression} value * @see http://php.net/manual/en/language.generators.syntax.php */ -var YieldFrom = Expression.extends(function YieldFrom(value, location) { - Expression.apply(this, [KIND, location]); - this.value = value; -}); - -module.exports = YieldFrom; +module.exports = Expression.extends( + KIND, + function YieldFrom(value, docs, location) { + Expression.apply(this, [KIND, docs, location]); + this.value = value; + }, +); diff --git a/src/index.js b/src/index.js index 84cd654c3..8e9b734d2 100644 --- a/src/index.js +++ b/src/index.js @@ -1,31 +1,32 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2020 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var lexer = require('./lexer'); -var parser = require('./parser'); -var tokens = require('./tokens'); -var AST = require('./ast'); +const lexer = require("./lexer"); +const parser = require("./parser"); +const tokens = require("./tokens"); +const AST = require("./ast"); /** - * @private combine structures + * @private */ function combine(src, to) { - var keys = Object.keys(src); - var i = keys.length; + const keys = Object.keys(src); + let i = keys.length; while (i--) { - var k = keys[i]; - var val = src[k]; + const k = keys[i]; + const val = src[k]; if (val === null) { delete to[k]; - } else if (typeof val === 'function') { + } else if (typeof val === "function") { to[k] = val.bind(to); } else if (Array.isArray(val)) { to[k] = Array.isArray(to[k]) ? to[k].concat(val) : val; - } else if (typeof val === 'object') { - to[k] = typeof to[k] === 'object' ? combine(val, to[k]) : val; + } else if (typeof val === "object") { + to[k] = typeof to[k] === "object" ? combine(val, to[k]) : val; } else { to[k] = val; } @@ -36,13 +37,16 @@ function combine(src, to) { /** * Initialise a new parser instance with the specified options * - * Usage : - * ```js + * @class + * @memberOf module:php-parser + * @tutorial Engine + * @example * var parser = require('php-parser'); * var instance = new parser({ * parser: { * extractDoc: true, - * suppressErrors: true + * suppressErrors: true, + * version: 704 // or '7.4' * }, * ast: { * withPositions: true @@ -56,45 +60,77 @@ function combine(src, to) { * var evalAST = instance.parseEval('some php code'); * var codeAST = instance.parseCode(' 900) { + throw new Error("Can only handle versions between 5.x to 8.x"); + } + } + } combine(options, this); + + // same version flags based on parser options + this.lexer.version = this.parser.version; } }; +/** + * Check if the inpyt is a buffer or a string + * @private + * @param {Buffer|String} buffer Input value that can be either a buffer or a string + * @return {String} Returns the string from input + */ +const getStringBuffer = function (buffer) { + return typeof buffer.write === "function" ? buffer.toString() : buffer; +}; + /** * Creates a new instance (Helper) * @param {Object} options * @return {Engine} * @private -*/ -engine.create = function(options) { - return new engine(options); + */ +Engine.create = function (options) { + return new Engine(options); }; /** * Evaluate the buffer * @private */ -engine.parseEval = function(buffer, options) { - var self = new engine(options); +Engine.parseEval = function (buffer, options) { + const self = new Engine(options); return self.parseEval(buffer); }; @@ -103,23 +139,24 @@ engine.parseEval = function(buffer, options) { * @param {String} buffer * @return {Program} */ -engine.prototype.parseEval = function(buffer) { +Engine.prototype.parseEval = function (buffer) { this.lexer.mode_eval = true; this.lexer.all_tokens = false; - return this.parser.parse(buffer, 'eval'); + buffer = getStringBuffer(buffer); + return this.parser.parse(buffer, "eval"); }; /** * Static function that parse a php code with open/close tags * @private */ -engine.parseCode = function(buffer, filename, options) { - if (typeof filename === 'object') { +Engine.parseCode = function (buffer, filename, options) { + if (typeof filename === "object" && !options) { // retro-compatibility options = filename; - filename = 'unknown'; + filename = "unknown"; } - var self = new engine(options); + const self = new Engine(options); return self.parseCode(buffer, filename); }; @@ -143,9 +180,10 @@ engine.parseCode = function(buffer, filename, options) { * @param {String} filename - Filename * @return {Program} */ -engine.prototype.parseCode = function(buffer, filename) { +Engine.prototype.parseCode = function (buffer, filename) { this.lexer.mode_eval = false; this.lexer.all_tokens = false; + buffer = getStringBuffer(buffer); return this.parser.parse(buffer, filename); }; @@ -153,28 +191,29 @@ engine.prototype.parseCode = function(buffer, filename) { * Split the buffer into tokens * @private */ -engine.tokenGetAll = function(buffer, options) { - var self = new engine(options); +Engine.tokenGetAll = function (buffer, options) { + const self = new Engine(options); return self.tokenGetAll(buffer); }; /** * Extract tokens from the specified buffer. * > Note that the output tokens are *STRICLY* similar to PHP function `token_get_all` - * @param {String} buffer - * @return {String[]} - Each item can be a string or an array with following informations [token_name, text, line_number] + * @param {string} buffer + * @return {Array} - Each item can be a string or an array with following informations [token_name, text, line_number] */ -engine.prototype.tokenGetAll = function(buffer) { +Engine.prototype.tokenGetAll = function (buffer) { this.lexer.mode_eval = false; this.lexer.all_tokens = true; - var EOF = this.lexer.EOF; - var names = this.tokens.values; + buffer = getStringBuffer(buffer); + const EOF = this.lexer.EOF; + const names = this.tokens.values; this.lexer.setInput(buffer); - var token = this.lexer.lex() || EOF; - var result = []; - while(token != EOF) { - var entry = this.lexer.yytext; - if (names.hasOwnProperty(token)) { + let token = this.lexer.lex() || EOF; + const result = []; + while (token != EOF) { + let entry = this.lexer.yytext; + if (Object.prototype.hasOwnProperty.call(names, token)) { entry = [names[token], entry, this.lexer.yylloc.first_line]; } result.push(entry); @@ -183,5 +222,18 @@ engine.prototype.tokenGetAll = function(buffer) { return result; }; +/** @module php-parser */ + // exports the function -module.exports = engine; +module.exports = Engine; + +// makes libraries public +module.exports.tokens = tokens; +module.exports.lexer = lexer; +module.exports.AST = AST; +module.exports.parser = parser; +module.exports.combine = combine; +module.exports.Engine = Engine; + +// allow the default export in index.d.ts +module.exports.default = Engine; diff --git a/src/lexer.js b/src/lexer.js index 7cb31f57c..c1cee6b35 100644 --- a/src/lexer.js +++ b/src/lexer.js @@ -1,24 +1,26 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; + /** * This is the php lexer. It will tokenize the string for helping the * parser to build the AST from its grammar. * - * @public @constructor {Lexer} - * @property {Integer} EOF - * @property {Boolean} all_tokens defines if all tokens must be retrieved (used by token_get_all only) - * @property {Boolean} comment_tokens extracts comments tokens - * @property {Boolean} mode_eval enables the evald mode (ignore opening tags) - * @property {Boolean} asp_tags disables by default asp tags mode - * @property {Boolean} short_tags enables by default short tags mode - * @property {Object} keywords List of php keyword - * @property {Object} castKeywords List of php keywords for type casting + * @constructor Lexer + * @memberOf module:php-parser + * @property {number} EOF + * @property {boolean} all_tokens defines if all tokens must be retrieved (used by token_get_all only) + * @property {boolean} comment_tokens extracts comments tokens + * @property {boolean} mode_eval enables the evald mode (ignore opening tags) + * @property {boolean} asp_tags disables by default asp tags mode + * @property {boolean} short_tags enables by default short tags mode + * @property {object} keywords List of php keyword + * @property {object} castKeywords List of php keywords for type casting */ -var lexer = function(engine) { +const Lexer = function (engine) { this.engine = engine; this.tok = this.engine.tokens.names; this.EOF = 1; @@ -27,110 +29,116 @@ var lexer = function(engine) { this.comment_tokens = false; this.mode_eval = false; this.asp_tags = false; - this.short_tags = true; + this.short_tags = false; + this.version = 803; this.yyprevcol = 0; this.keywords = { - "__class__": this.tok.T_CLASS_C, - "__trait__": this.tok.T_TRAIT_C, - "__function__": this.tok.T_FUNC_C, - "__method__": this.tok.T_METHOD_C, - "__line__": this.tok.T_LINE, - "__file__": this.tok.T_FILE, - "__dir__": this.tok.T_DIR, - "__namespace__": this.tok.T_NS_C, - 'exit': this.tok.T_EXIT, - 'die': this.tok.T_EXIT, - 'function': this.tok.T_FUNCTION, - "const": this.tok.T_CONST, - "return": this.tok.T_RETURN, - "try": this.tok.T_TRY, - "catch": this.tok.T_CATCH, - "finally": this.tok.T_FINALLY, - "throw": this.tok.T_THROW, - "if": this.tok.T_IF, - "elseif": this.tok.T_ELSEIF, - "endif": this.tok.T_ENDIF, - "else": this.tok.T_ELSE, - "while": this.tok.T_WHILE, - "endwhile": this.tok.T_ENDWHILE, - "do": this.tok.T_DO, - "for": this.tok.T_FOR, - "endfor": this.tok.T_ENDFOR, - "foreach": this.tok.T_FOREACH, - "endforeach": this.tok.T_ENDFOREACH, - "declare": this.tok.T_DECLARE, - "enddeclare": this.tok.T_ENDDECLARE, - "instanceof": this.tok.T_INSTANCEOF, - "as": this.tok.T_AS, - "switch": this.tok.T_SWITCH, - "endswitch": this.tok.T_ENDSWITCH, - "case": this.tok.T_CASE, - "default": this.tok.T_DEFAULT, - "break": this.tok.T_BREAK, - "continue": this.tok.T_CONTINUE, - "goto": this.tok.T_GOTO, - "echo": this.tok.T_ECHO, - "print": this.tok.T_PRINT, - "class": this.tok.T_CLASS, - "interface": this.tok.T_INTERFACE, - "trait": this.tok.T_TRAIT, - "extends": this.tok.T_EXTENDS, - "implements": this.tok.T_IMPLEMENTS, - "new": this.tok.T_NEW, - "clone": this.tok.T_CLONE, - "var": this.tok.T_VAR, - "eval": this.tok.T_EVAL, - "include": this.tok.T_INCLUDE, - "include_once": this.tok.T_INCLUDE_ONCE, - "require": this.tok.T_REQUIRE, - "require_once": this.tok.T_REQUIRE_ONCE, - "namespace": this.tok.T_NAMESPACE, - "use": this.tok.T_USE, - "insteadof": this.tok.T_INSTEADOF, - "global": this.tok.T_GLOBAL, - "isset": this.tok.T_ISSET, - "empty": this.tok.T_EMPTY, - "__halt_compiler": this.tok.T_HALT_COMPILER, - "static": this.tok.T_STATIC, - "abstract": this.tok.T_ABSTRACT, - "final": this.tok.T_FINAL, - "private": this.tok.T_PRIVATE, - "protected": this.tok.T_PROTECTED, - "public": this.tok.T_PUBLIC, - "unset": this.tok.T_UNSET, - "list": this.tok.T_LIST, - "array": this.tok.T_ARRAY, - "callable": this.tok.T_CALLABLE, - "or": this.tok.T_LOGICAL_OR, - "and": this.tok.T_LOGICAL_AND, - "xor": this.tok.T_LOGICAL_XOR + __class__: this.tok.T_CLASS_C, + __trait__: this.tok.T_TRAIT_C, + __function__: this.tok.T_FUNC_C, + __method__: this.tok.T_METHOD_C, + __line__: this.tok.T_LINE, + __file__: this.tok.T_FILE, + __dir__: this.tok.T_DIR, + __namespace__: this.tok.T_NS_C, + exit: this.tok.T_EXIT, + die: this.tok.T_EXIT, + function: this.tok.T_FUNCTION, + const: this.tok.T_CONST, + return: this.tok.T_RETURN, + try: this.tok.T_TRY, + catch: this.tok.T_CATCH, + finally: this.tok.T_FINALLY, + throw: this.tok.T_THROW, + if: this.tok.T_IF, + elseif: this.tok.T_ELSEIF, + endif: this.tok.T_ENDIF, + else: this.tok.T_ELSE, + while: this.tok.T_WHILE, + endwhile: this.tok.T_ENDWHILE, + do: this.tok.T_DO, + for: this.tok.T_FOR, + endfor: this.tok.T_ENDFOR, + foreach: this.tok.T_FOREACH, + endforeach: this.tok.T_ENDFOREACH, + declare: this.tok.T_DECLARE, + enddeclare: this.tok.T_ENDDECLARE, + instanceof: this.tok.T_INSTANCEOF, + as: this.tok.T_AS, + switch: this.tok.T_SWITCH, + endswitch: this.tok.T_ENDSWITCH, + case: this.tok.T_CASE, + default: this.tok.T_DEFAULT, + break: this.tok.T_BREAK, + continue: this.tok.T_CONTINUE, + goto: this.tok.T_GOTO, + echo: this.tok.T_ECHO, + print: this.tok.T_PRINT, + class: this.tok.T_CLASS, + interface: this.tok.T_INTERFACE, + trait: this.tok.T_TRAIT, + enum: this.tok.T_ENUM, + extends: this.tok.T_EXTENDS, + implements: this.tok.T_IMPLEMENTS, + new: this.tok.T_NEW, + clone: this.tok.T_CLONE, + var: this.tok.T_VAR, + eval: this.tok.T_EVAL, + include: this.tok.T_INCLUDE, + include_once: this.tok.T_INCLUDE_ONCE, + require: this.tok.T_REQUIRE, + require_once: this.tok.T_REQUIRE_ONCE, + namespace: this.tok.T_NAMESPACE, + use: this.tok.T_USE, + insteadof: this.tok.T_INSTEADOF, + global: this.tok.T_GLOBAL, + isset: this.tok.T_ISSET, + empty: this.tok.T_EMPTY, + __halt_compiler: this.tok.T_HALT_COMPILER, + static: this.tok.T_STATIC, + abstract: this.tok.T_ABSTRACT, + final: this.tok.T_FINAL, + private: this.tok.T_PRIVATE, + protected: this.tok.T_PROTECTED, + public: this.tok.T_PUBLIC, + unset: this.tok.T_UNSET, + list: this.tok.T_LIST, + array: this.tok.T_ARRAY, + callable: this.tok.T_CALLABLE, + or: this.tok.T_LOGICAL_OR, + and: this.tok.T_LOGICAL_AND, + xor: this.tok.T_LOGICAL_XOR, + match: this.tok.T_MATCH, + readonly: this.tok.T_READ_ONLY, }; this.castKeywords = { - 'int': this.tok.T_INT_CAST, - 'integer': this.tok.T_INT_CAST, - "real": this.tok.T_DOUBLE_CAST, - "double": this.tok.T_DOUBLE_CAST, - "float": this.tok.T_DOUBLE_CAST, - "string": this.tok.T_STRING_CAST, - "binary": this.tok.T_STRING_CAST, - "array": this.tok.T_ARRAY_CAST, - "object": this.tok.T_OBJECT_CAST, - "bool": this.tok.T_BOOL_CAST, - "boolean": this.tok.T_BOOL_CAST, - "unset": this.tok.T_UNSET_CAST + int: this.tok.T_INT_CAST, + integer: this.tok.T_INT_CAST, + real: this.tok.T_DOUBLE_CAST, + double: this.tok.T_DOUBLE_CAST, + float: this.tok.T_DOUBLE_CAST, + string: this.tok.T_STRING_CAST, + binary: this.tok.T_STRING_CAST, + array: this.tok.T_ARRAY_CAST, + object: this.tok.T_OBJECT_CAST, + bool: this.tok.T_BOOL_CAST, + boolean: this.tok.T_BOOL_CAST, + unset: this.tok.T_UNSET_CAST, }; }; /** * Initialize the lexer with the specified input + * @function Lexer#setInput + * @memberOf module:php-parser */ -lexer.prototype.setInput = function(input) { +Lexer.prototype.setInput = function (input) { this._input = input; this.size = input.length; this.yylineno = 1; this.offset = 0; this.yyprevcol = 0; - this.yytext = ''; + this.yytext = ""; this.yylloc = { first_offset: 0, first_line: 1, @@ -139,33 +147,61 @@ lexer.prototype.setInput = function(input) { prev_line: 1, prev_column: 0, last_line: 1, - last_column: 0 + last_column: 0, }; this.tokens = []; - this.conditionStack = []; + if (this.version > 703) { + this.keywords.fn = this.tok.T_FN; + } else { + delete this.keywords.fn; + } this.done = this.offset >= this.size; if (!this.all_tokens && this.mode_eval) { - this.begin('ST_IN_SCRIPTING'); + this.conditionStack = ["INITIAL"]; + this.begin("ST_IN_SCRIPTING"); } else { - this.begin('INITIAL'); + this.conditionStack = []; + this.begin("INITIAL"); } + // https://github.com/php/php-src/blob/999e32b65a8a4bb59e27e538fa68ffae4b99d863/Zend/zend_language_scanner.h#L59 + // Used for heredoc and nowdoc + this.heredoc_label = { + label: "", + length: 0, + indentation: 0, + indentation_uses_spaces: false, + finished: false, + /* + * this used for parser to detemine the if current node segment is first encaps node. + * if ture, the indentation will remove from the begining. and if false, the prev node + * might be a variable '}' ,and the leading spaces should not be removed util meet the + * first \n + */ + first_encaps_node: false, + // for backward compatible + /* istanbul ignore next */ + toString: function () { + this.label; + }, + }; return this; }; - /** * consumes and returns one char from the input + * @function Lexer#input + * @memberOf module:php-parser */ -lexer.prototype.input = function(size) { - var ch = this._input[this.offset]; - if (!ch) return ''; +Lexer.prototype.input = function () { + const ch = this._input[this.offset]; + if (!ch) return ""; this.yytext += ch; - this.offset ++; - if ( ch === '\r' && this._input[this.offset] === '\n' ) { - this.yytext += '\n'; + this.offset++; + if (ch === "\r" && this._input[this.offset] === "\n") { + this.yytext += "\n"; this.offset++; } - if (ch === '\n' || ch === '\r') { + if (ch === "\n" || ch === "\r") { this.yylloc.last_line = ++this.yylineno; this.yyprevcol = this.yylloc.last_column; this.yylloc.last_column = 0; @@ -177,21 +213,29 @@ lexer.prototype.input = function(size) { /** * revert eating specified size + * @function Lexer#unput + * @memberOf module:php-parser */ -lexer.prototype.unput = function(size) { +Lexer.prototype.unput = function (size) { if (size === 1) { // 1 char unput (most cases) - this.offset --; - if (this._input[this.offset] === '\n' && this._input[this.offset - 1] === '\r') { - this.offset --; - size ++; + this.offset--; + if ( + this._input[this.offset] === "\n" && + this._input[this.offset - 1] === "\r" + ) { + this.offset--; + size++; } - if (this._input[this.offset] === '\r' || this._input[this.offset] === '\n') { - this.yylloc.last_line --; - this.yylineno --; + if ( + this._input[this.offset] === "\r" || + this._input[this.offset] === "\n" + ) { + this.yylloc.last_line--; + this.yylineno--; this.yylloc.last_column = this.yyprevcol; } else { - this.yylloc.last_column --; + this.yylloc.last_column--; } this.yytext = this.yytext.substring(0, this.yytext.length - size); } else if (size > 0) { @@ -201,26 +245,26 @@ lexer.prototype.unput = function(size) { // re-calculate position this.yylloc.last_line = this.yylloc.first_line; this.yylloc.last_column = this.yyprevcol = this.yylloc.first_column; - for(var i = 0; i < this.yytext.length; i++) { - var c = this.yytext[i]; - if (c === '\r') { + for (let i = 0; i < this.yytext.length; i++) { + let c = this.yytext[i]; + if (c === "\r") { c = this.yytext[++i]; this.yyprevcol = this.yylloc.last_column; - this.yylloc.last_line ++; + this.yylloc.last_line++; this.yylloc.last_column = 0; - if (c !== '\n') { - if (c === '\r') { - this.yylloc.last_line ++; + if (c !== "\n") { + if (c === "\r") { + this.yylloc.last_line++; } else { - this.yylloc.last_column ++; + this.yylloc.last_column++; } } - } else if (c === '\n') { + } else if (c === "\n") { this.yyprevcol = this.yylloc.last_column; - this.yylloc.last_line ++; + this.yylloc.last_line++; this.yylloc.last_column = 0; } else { - this.yylloc.last_column ++; + this.yylloc.last_column++; } } this.yylineno = this.yylloc.last_line; @@ -235,38 +279,65 @@ lexer.prototype.unput = function(size) { return this; }; -// check if the text matches -lexer.prototype.tryMatch = function(text) { +/** + * check if the text matches + * @function Lexer#tryMatch + * @memberOf module:php-parser + * @param {string} text + * @returns {boolean} + */ +Lexer.prototype.tryMatch = function (text) { return text === this.ahead(text.length); }; -// check if the text matches -lexer.prototype.tryMatchCaseless = function(text) { +/** + * check if the text matches + * @function Lexer#tryMatchCaseless + * @memberOf module:php-parser + * @param {string} text + * @returns {boolean} + */ +Lexer.prototype.tryMatchCaseless = function (text) { return text === this.ahead(text.length).toLowerCase(); }; -// look ahead -lexer.prototype.ahead = function(size) { - var text = this._input.substring(this.offset, this.offset + size); - if (text[text.length - 1] === '\r' && this._input[this.offset + size + 1] === '\n') { - text += '\n'; +/** + * look ahead + * @function Lexer#ahead + * @memberOf module:php-parser + * @param {number} size + * @returns {string} + */ +Lexer.prototype.ahead = function (size) { + let text = this._input.substring(this.offset, this.offset + size); + if ( + text[text.length - 1] === "\r" && + this._input[this.offset + size + 1] === "\n" + ) { + text += "\n"; } return text; }; -// consume the specified size -lexer.prototype.consume = function(size) { - for(var i = 0; i < size; i++) { - var ch = this._input[this.offset]; +/** + * consume the specified size + * @function Lexer#consume + * @memberOf module:php-parser + * @param {number} size + * @returns {Lexer} + */ +Lexer.prototype.consume = function (size) { + for (let i = 0; i < size; i++) { + const ch = this._input[this.offset]; if (!ch) break; this.yytext += ch; - this.offset ++; - if ( ch === '\r' && this._input[this.offset] === '\n' ) { - this.yytext += '\n'; + this.offset++; + if (ch === "\r" && this._input[this.offset] === "\n") { + this.yytext += "\n"; this.offset++; i++; } - if (ch === '\n' || ch === '\r') { + if (ch === "\n" || ch === "\r") { this.yylloc.last_line = ++this.yylineno; this.yyprevcol = this.yylloc.last_column; this.yylloc.last_column = 0; @@ -279,8 +350,10 @@ lexer.prototype.consume = function(size) { /** * Gets the current state + * @function Lexer#getState + * @memberOf module:php-parser */ -lexer.prototype.getState = function() { +Lexer.prototype.getState = function () { return { yytext: this.yytext, offset: this.offset, @@ -291,54 +364,71 @@ lexer.prototype.getState = function() { first_line: this.yylloc.first_line, first_column: this.yylloc.first_column, last_line: this.yylloc.last_line, - last_column: this.yylloc.last_column - } + last_column: this.yylloc.last_column, + }, + heredoc_label: this.heredoc_label, }; }; /** * Sets the current lexer state + * @function Lexer#setState + * @memberOf module:php-parser */ -lexer.prototype.setState = function(state) { +Lexer.prototype.setState = function (state) { this.yytext = state.yytext; this.offset = state.offset; this.yylineno = state.yylineno; this.yyprevcol = state.yyprevcol; this.yylloc = state.yylloc; + if (state.heredoc_label) { + this.heredoc_label = state.heredoc_label; + } return this; }; -// prepend next token -lexer.prototype.appendToken = function(value, ahead) { +/** + * prepend next token + * @function Lexer#appendToken + * @memberOf module:php-parser + * @param {*} value + * @param {*} ahead + * @returns {Lexer} + */ +Lexer.prototype.appendToken = function (value, ahead) { this.tokens.push([value, ahead]); return this; }; -// return next match that has a token -lexer.prototype.lex = function() { +/** + * return next match that has a token + * @function Lexer#lex + * @memberOf module:php-parser + * @returns {number|string} + */ +Lexer.prototype.lex = function () { this.yylloc.prev_offset = this.offset; this.yylloc.prev_line = this.yylloc.last_line; this.yylloc.prev_column = this.yylloc.last_column; - var token = this.next() || this.lex(); + let token = this.next() || this.lex(); if (!this.all_tokens) { - while( - token === this.tok.T_WHITESPACE // ignore white space - || ( - !this.comment_tokens && ( - token === this.tok.T_COMMENT // ignore single lines comments - || token === this.tok.T_DOC_COMMENT // ignore doc comments - ) - ) - || ( - // ignore open tags - token === this.tok.T_OPEN_TAG - ) + while ( + token === this.tok.T_WHITESPACE || // ignore white space + (!this.comment_tokens && + (token === this.tok.T_COMMENT || // ignore single lines comments + token === this.tok.T_DOC_COMMENT)) || // ignore doc comments + // ignore open tags + token === this.tok.T_OPEN_TAG ) { token = this.next() || this.lex(); } - if (!this.mode_eval && token == this.tok.T_OPEN_TAG_WITH_ECHO) { + if (token == this.tok.T_OPEN_TAG_WITH_ECHO) { + // https://github.com/php/php-src/blob/7ff186434e82ee7be7c59d0db9a976641cf7b09c/Zend/zend_compile.c#L1683 // open tag with echo statement return this.tok.T_ECHO; + } else if (token === this.tok.T_CLOSE_TAG) { + // https://github.com/php/php-src/blob/7ff186434e82ee7be7c59d0db9a976641cf7b09c/Zend/zend_compile.c#L1680 + return ";"; /* implicit ; */ } } if (!this.yylloc.prev_offset) { @@ -352,39 +442,57 @@ lexer.prototype.lex = function() { return token; }; -// activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) -lexer.prototype.begin = function(condition) { +/** + * activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) + * @function Lexer#begin + * @memberOf module:php-parser + * @param {*} condition + * @returns {Lexer} + */ +Lexer.prototype.begin = function (condition) { this.conditionStack.push(condition); this.curCondition = condition; - this.stateCb = this['match' + condition]; - if (typeof this.stateCb !== 'function') { - throw new Error('Undefined condition state "'+condition+'"'); + this.stateCb = this["match" + condition]; + /* istanbul ignore next */ + if (typeof this.stateCb !== "function") { + throw new Error('Undefined condition state "' + condition + '"'); } return this; }; -// pop the previously active lexer condition state off the condition stack -lexer.prototype.popState = function() { - var n = this.conditionStack.length - 1; - var condition = (n > 0) ? this.conditionStack.pop() : this.conditionStack[0]; +/** + * pop the previously active lexer condition state off the condition stack + * @function Lexer#popState + * @memberOf module:php-parser + * @returns {string|*} + */ +Lexer.prototype.popState = function () { + const n = this.conditionStack.length - 1; + const condition = n > 0 ? this.conditionStack.pop() : this.conditionStack[0]; this.curCondition = this.conditionStack[this.conditionStack.length - 1]; - this.stateCb = this['match' + this.curCondition]; - if (typeof this.stateCb !== 'function') { - throw new Error('Undefined condition state "'+this.curCondition+'"'); + this.stateCb = this["match" + this.curCondition]; + /* istanbul ignore next */ + if (typeof this.stateCb !== "function") { + throw new Error('Undefined condition state "' + this.curCondition + '"'); } return condition; }; -// return next match in input -lexer.prototype.next = function () { - var token; +/** + * return next match in input + * @function Lexer#next + * @memberOf module:php-parser + * @returns {number|*} + */ +Lexer.prototype.next = function () { + let token; if (!this._input) { this.done = true; } this.yylloc.first_offset = this.offset; this.yylloc.first_line = this.yylloc.last_line; this.yylloc.first_column = this.yylloc.last_column; - this.yytext = ''; + this.yytext = ""; if (this.done) { this.yylloc.prev_offset = this.yylloc.first_offset; this.yylloc.prev_line = this.yylloc.first_line; @@ -393,7 +501,7 @@ lexer.prototype.next = function () { } if (this.tokens.length > 0) { token = this.tokens.shift(); - if (typeof token[1] === 'object') { + if (typeof token[1] === "object") { this.setState(token[1]); } else { this.consume(token[1]); @@ -405,39 +513,49 @@ lexer.prototype.next = function () { if (this.offset >= this.size && this.tokens.length === 0) { this.done = true; } + /* istanbul ignore next */ if (this.debug) { - var tName = token; - if (typeof tName === 'number') { + let tName = token; + if (typeof tName === "number") { tName = this.engine.tokens.values[tName]; } else { - tName = '"'+tName+'"'; + tName = '"' + tName + '"'; } - var e = new Error( + const e = new Error( tName + - '\tfrom ' + this.yylloc.first_line + ',' + this.yylloc.first_column + - '\t - to ' + this.yylloc.last_line + ',' + this.yylloc.last_column + - '\t"'+this.yytext+'"' + "\tfrom " + + this.yylloc.first_line + + "," + + this.yylloc.first_column + + "\t - to " + + this.yylloc.last_line + + "," + + this.yylloc.last_column + + '\t"' + + this.yytext + + '"', ); - console.log(e.stack); + // eslint-disable-next-line no-console + console.error(e.stack); } return token; }; - // extends the lexer with states [ - require('./lexer/comments.js'), - require('./lexer/initial.js'), - require('./lexer/numbers.js'), - require('./lexer/property.js'), - require('./lexer/scripting.js'), - require('./lexer/strings.js'), - require('./lexer/tokens.js'), - require('./lexer/utils.js') + require("./lexer/attribute.js"), + require("./lexer/comments.js"), + require("./lexer/initial.js"), + require("./lexer/numbers.js"), + require("./lexer/property.js"), + require("./lexer/scripting.js"), + require("./lexer/strings.js"), + require("./lexer/tokens.js"), + require("./lexer/utils.js"), ].forEach(function (ext) { - for(var k in ext) { - lexer.prototype[k] = ext[k]; + for (const k in ext) { + Lexer.prototype[k] = ext[k]; } }); -module.exports = lexer; +module.exports = Lexer; diff --git a/src/lexer/attribute.js b/src/lexer/attribute.js new file mode 100644 index 000000000..b3421baea --- /dev/null +++ b/src/lexer/attribute.js @@ -0,0 +1,85 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +module.exports = { + attributeIndex: 0, + attributeListDepth: {}, + matchST_ATTRIBUTE: function () { + let ch = this.input(); + if (this.is_WHITESPACE()) { + do { + ch = this.input(); + } while (this.is_WHITESPACE()); + this.unput(1); + return null; + } + switch (ch) { + case "]": + if (this.attributeListDepth[this.attributeIndex] === 0) { + delete this.attributeListDepth[this.attributeIndex]; + this.attributeIndex--; + this.popState(); + } else { + /* istanbul ignore next */ + this.attributeListDepth[this.attributeIndex]--; + } + return "]"; + case "(": + case ")": + case ":": + case "=": + case "|": + case "&": + case "^": + case "-": + case "+": + case "*": + case "%": + case "~": + case "<": + case ">": + case "!": + case ".": + return this.consume_TOKEN(); + case "[": + this.attributeListDepth[this.attributeIndex]++; + return "["; + case ",": + return ","; + case '"': + return this.ST_DOUBLE_QUOTES(); + case "'": + return this.T_CONSTANT_ENCAPSED_STRING(); + case "/": + if (this._input[this.offset] === "/") { + return this.T_COMMENT(); + } else if (this._input[this.offset] === "*") { + this.input(); + return this.T_DOC_COMMENT(); + } else { + return this.consume_TOKEN(); + } + } + if (this.is_LABEL_START() || ch === "\\") { + while (this.offset < this.size) { + const ch = this.input(); + if (!(this.is_LABEL() || ch === "\\")) { + if (ch) this.unput(1); + break; + } + } + return this.T_STRING(); + } else if (this.is_NUM()) { + return this.consume_NUM(); + } + + /* istanbul ignore next */ + throw new Error( + `Bad terminal sequence "${ch}" at line ${this.yylineno} (offset ${this.offset})`, + ); + }, +}; diff --git a/src/lexer/comments.js b/src/lexer/comments.js index 69673e629..43501d701 100644 --- a/src/lexer/comments.js +++ b/src/lexer/comments.js @@ -1,55 +1,63 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ - "use strict"; module.exports = { - /** + /* * Reads a single line comment - * @see */ - T_COMMENT: function() { - while(this.offset < this.size) { - var ch = this.input(); - if (ch === '\n' || ch === '\r') { + T_COMMENT: function () { + while (this.offset < this.size) { + const ch = this.input(); + if (ch === "\n" || ch === "\r") { return this.tok.T_COMMENT; - } else if (ch === '?' && !this.aspTagMode && this._input[this.offset] === '>') { + } else if ( + ch === "?" && + !this.aspTagMode && + this._input[this.offset] === ">" + ) { this.unput(1); return this.tok.T_COMMENT; - } else if (ch === '%' && this.aspTagMode && this._input[this.offset] === '>') { + } else if ( + ch === "%" && + this.aspTagMode && + this._input[this.offset] === ">" + ) { this.unput(1); return this.tok.T_COMMENT; } } return this.tok.T_COMMENT; }, - /** + /* * Behaviour : https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1927 */ - T_DOC_COMMENT: function() { - var ch = this.input(); - var token = this.tok.T_COMMENT; - if (ch === '*') { // started with '/*' , check is next is '*' + T_DOC_COMMENT: function () { + let ch = this.input(); + let token = this.tok.T_COMMENT; + if (ch === "*") { + // started with '/*' , check is next is '*' ch = this.input(); - if (this.is_WHITESPACE()) { // check if next is WHITESPACE + if (this.is_WHITESPACE()) { + // check if next is WHITESPACE token = this.tok.T_DOC_COMMENT; } - if (ch === '/') { + if (ch === "/") { return token; } else { this.unput(1); // reset } } - while(this.offset < this.size) { + while (this.offset < this.size) { ch = this.input(); - if (ch === '*' && this._input[this.offset] === '/') { + if (ch === "*" && this._input[this.offset] === "/") { this.input(); break; } } return token; - } + }, }; diff --git a/src/lexer/initial.js b/src/lexer/initial.js index 4eb6467aa..1524b8048 100644 --- a/src/lexer/initial.js +++ b/src/lexer/initial.js @@ -1,13 +1,15 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; + module.exports = { - nextINITIAL: function() { + nextINITIAL: function () { if ( - this.conditionStack.length > 1 - && this.conditionStack[this.conditionStack.length - 1] === 'INITIAL' + this.conditionStack.length > 1 && + this.conditionStack[this.conditionStack.length - 1] === "INITIAL" ) { // Return to HEREDOC/ST_DOUBLE_QUOTES mode this.popState(); @@ -16,18 +18,20 @@ module.exports = { } return this; }, - matchINITIAL: function() { - while(this.offset < this.size) { - var ch = this.input(); - if (ch == '<') { + matchINITIAL: function () { + while (this.offset < this.size) { + let ch = this.input(); + if (ch == "<") { ch = this.ahead(1); - if (ch == '?') { - if (this.tryMatch('?=')) { - this.unput(1).appendToken(this.tok.T_OPEN_TAG_WITH_ECHO, 3).nextINITIAL(); + if (ch == "?") { + if (this.tryMatch("?=")) { + this.unput(1) + .appendToken(this.tok.T_OPEN_TAG_WITH_ECHO, 3) + .nextINITIAL(); break; - } else if (this.tryMatchCaseless('?php')) { + } else if (this.tryMatchCaseless("?php")) { ch = this._input[this.offset + 4]; - if (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r') { + if (ch === " " || ch === "\t" || ch === "\n" || ch === "\r") { this.unput(1).appendToken(this.tok.T_OPEN_TAG, 6).nextINITIAL(); break; } @@ -36,10 +40,12 @@ module.exports = { this.unput(1).appendToken(this.tok.T_OPEN_TAG, 2).nextINITIAL(); break; } - } else if(this.asp_tags && ch == '%') { - if (this.tryMatch('%=')) { + } else if (this.asp_tags && ch == "%") { + if (this.tryMatch("%=")) { this.aspTagMode = true; - this.unput(1).appendToken(this.tok.T_OPEN_TAG_WITH_ECHO, 3).nextINITIAL(); + this.unput(1) + .appendToken(this.tok.T_OPEN_TAG_WITH_ECHO, 3) + .nextINITIAL(); break; } else { this.aspTagMode = true; @@ -54,5 +60,5 @@ module.exports = { } else { return false; } - } + }, }; diff --git a/src/lexer/numbers.js b/src/lexer/numbers.js index 5a649e29d..0d6239461 100644 --- a/src/lexer/numbers.js +++ b/src/lexer/numbers.js @@ -1,87 +1,122 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ - "use strict"; /* istanbul ignore else */ -if (process.arch == 'x64') { - var SIZEOF_LONG = 8; - var MAX_LENGTH_OF_LONG = 19; - var long_min_digits = "9223372036854775808"; -} else { - var SIZEOF_LONG = 4; - var MAX_LENGTH_OF_LONG = 10; - var long_min_digits = "2147483648"; +let MAX_LENGTH_OF_LONG = 10; +let long_min_digits = "2147483648"; +if (process.arch == "x64") { + MAX_LENGTH_OF_LONG = 19; + long_min_digits = "9223372036854775808"; } module.exports = { - consume_NUM: function() { - var ch = this.yytext[0]; - var hasPoint = this.yytext[0] === '.'; - if (ch === '0') { + consume_NUM: function () { + let ch = this.yytext[0]; + let hasPoint = ch === "."; + if (ch === "0") { ch = this.input(); // check if hexa - if (ch === 'x' || ch === 'X') { - this.input(); - if (this.is_HEX()) { + if (ch === "x" || ch === "X") { + ch = this.input(); + if (ch !== "_" && this.is_HEX()) { return this.consume_HNUM(); } else { - this.unput(2); + this.unput(ch ? 2 : 1); } - } else if (ch === 'b' || ch === 'B') { + // check binary notation + } else if (ch === "b" || ch === "B") { ch = this.input(); - if (ch === '0' || ch === '1') { + if ((ch !== "_" && ch === "0") || ch === "1") { return this.consume_BNUM(); } else { - this.unput(2); + this.unput(ch ? 2 : 1); + } + } else if (ch === "o" || ch === "O") { + ch = this.input(); + if (ch !== "_" && this.is_OCTAL()) { + return this.consume_ONUM(); + } else { + this.unput(ch ? 2 : 1); } } else if (!this.is_NUM()) { - this.unput(1); + if (ch) this.unput(1); } } - while(this.offset < this.size) { + while (this.offset < this.size) { + const prev = ch; ch = this.input(); - if (!this.is_NUM()) { - if (ch === '.' && !hasPoint) { - hasPoint = true; - } else if (ch === 'e' || ch === 'E') { - ch = this.input(); - if (ch === '+' || ch === '-') { - ch = this.input(); - if (this.is_NUM()) { - this.consume_LNUM(); - return this.tok.T_DNUMBER; - } else { - if (ch) this.unput(3); - break; - } - } else if (this.is_NUM()) { - this.consume_LNUM(); - return this.tok.T_DNUMBER; - } else { - if (ch) this.unput(2); - break; - } - } else { + + if (ch === "_") { + if (prev === "_") { + // restriction : next to underscore / 1__1; + this.unput(2); // keep 1 + break; + } + if (prev === ".") { + // next to decimal point "1._0" + this.unput(1); // keep 1. + break; + } + if (prev === "e" || prev === "E") { + // next to e "1e_10" + this.unput(2); // keep 1 + break; + } + } else if (ch === ".") { + if (hasPoint) { + // no multiple points "1.0.5" + this.unput(1); // keep 1.0 + break; + } + if (prev === "_") { + // next to decimal point "1_.0" + this.unput(2); // keep 1 + break; + } + hasPoint = true; + continue; + } else if (ch === "e" || ch === "E") { + if (prev === "_") { + // next to e "1_e10" this.unput(1); break; } + let undo = 2; + ch = this.input(); + if (ch === "+" || ch === "-") { + // 1e-5 + undo = 3; + ch = this.input(); + } + if (this.is_NUM_START()) { + this.consume_LNUM(); + return this.tok.T_DNUMBER; + } + this.unput(ch ? undo : undo - 1); // keep only 1 + break; + } + + if (!this.is_NUM()) { + // example : 10.0a + if (ch) this.unput(1); // keep 10.0 + break; } } + if (hasPoint) { return this.tok.T_DNUMBER; } else if (this.yytext.length < MAX_LENGTH_OF_LONG - 1) { return this.tok.T_LNUMBER; } else { if ( - this.yytext.length < MAX_LENGTH_OF_LONG || ( - this.yytext.length == MAX_LENGTH_OF_LONG - && this.yytext < long_min_digits - ) + this.yytext.length < MAX_LENGTH_OF_LONG || + (this.yytext.length == MAX_LENGTH_OF_LONG && + this.yytext < long_min_digits) ) { return this.tok.T_LNUMBER; } @@ -89,37 +124,48 @@ module.exports = { } }, // read hexa - consume_HNUM: function() { - while(this.offset < this.size) { - this.input(); + consume_HNUM: function () { + while (this.offset < this.size) { + const ch = this.input(); if (!this.is_HEX()) { - this.unput(1); + if (ch) this.unput(1); break; } } return this.tok.T_LNUMBER; }, // read a generic number - consume_LNUM: function() { - while(this.offset < this.size) { - this.input(); + consume_LNUM: function () { + while (this.offset < this.size) { + const ch = this.input(); if (!this.is_NUM()) { - this.unput(1); + if (ch) this.unput(1); break; } } return this.tok.T_LNUMBER; }, // read binary - consume_BNUM: function() { - var ch; - while(this.offset < this.size) { + consume_BNUM: function () { + let ch; + while (this.offset < this.size) { ch = this.input(); - if (ch !== '0' && ch !== '1') { + if (ch !== "0" && ch !== "1" && ch !== "_") { if (ch) this.unput(1); break; } } return this.tok.T_LNUMBER; - } + }, + // read an octal number + consume_ONUM: function () { + while (this.offset < this.size) { + const ch = this.input(); + if (!this.is_OCTAL()) { + if (ch) this.unput(1); + break; + } + } + return this.tok.T_LNUMBER; + }, }; diff --git a/src/lexer/property.js b/src/lexer/property.js index 7b94fa49c..8d2c00259 100644 --- a/src/lexer/property.js +++ b/src/lexer/property.js @@ -1,18 +1,22 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; + module.exports = { - matchST_LOOKING_FOR_PROPERTY: function() { - var ch = this.input(); - if (ch === '-') { + matchST_LOOKING_FOR_PROPERTY: function () { + let ch = this.input(); + if (ch === "-") { ch = this.input(); - if (ch === '>') { + if (ch === ">") { // https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1296 return this.tok.T_OBJECT_OPERATOR; } if (ch) this.unput(1); + } else if (this.is_WHITESPACE()) { + return this.tok.T_WHITESPACE; } else if (this.is_LABEL_START()) { // https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1300 this.consume_LABEL(); @@ -24,53 +28,69 @@ module.exports = { if (ch) this.unput(1); return false; }, - matchST_LOOKING_FOR_VARNAME: function() { - var ch = this.input(); + matchST_LOOKING_FOR_VARNAME: function () { + let ch = this.input(); + + // SHIFT STATE + this.popState(); + this.begin("ST_IN_SCRIPTING"); + if (this.is_LABEL_START()) { this.consume_LABEL(); ch = this.input(); - this.popState(); - if (ch === '[' || ch === '}') { - this.begin('ST_IN_SCRIPTING'); + if (ch === "[" || ch === "}") { this.unput(1); return this.tok.T_STRING_VARNAME; } else { + // any char (that's started with a label sequence) this.unput(this.yytext.length); - return false; } } else { + // any char (thats not a label start sequence) if (ch) this.unput(1); - this.popState(); - this.begin('ST_IN_SCRIPTING'); - // console.log(this.yylineno, 'ST_LOOKING_FOR_VARNAME', this._input[this.offset - 1], this.conditionStack); - return false; } + // stops looking for a varname and starts the scripting mode + return false; }, - matchST_VAR_OFFSET: function() { - var ch = this.input(); - if (this.is_NUM()) { + matchST_VAR_OFFSET: function () { + const ch = this.input(); + if (this.is_NUM_START()) { this.consume_NUM(); return this.tok.T_NUM_STRING; - } else if (ch === ']') { + } else if (ch === "]") { this.popState(); - return ']'; - } else if (ch === '$') { + return "]"; + } else if (ch === "$") { this.input(); if (this.is_LABEL_START()) { this.consume_LABEL(); return this.tok.T_VARIABLE; } else { - throw new Error('Unexpected terminal'); + /* istanbul ignore next */ + throw new Error("Unexpected terminal"); } } else if (this.is_LABEL_START()) { this.consume_LABEL(); return this.tok.T_STRING; - } else if (this.is_WHITESPACE() || ch === '\\' || ch === '\'' || ch === '#') { + } else if ( + this.is_WHITESPACE() || + ch === "\\" || + ch === "'" || + ch === "#" + ) { return this.tok.T_ENCAPSED_AND_WHITESPACE; - } else if (ch === '[' || ch === '{' || ch === '}' || ch === '"' || ch === '`' || this.is_TOKEN()) { + } else if ( + ch === "[" || + ch === "{" || + ch === "}" || + ch === '"' || + ch === "`" || + this.is_TOKEN() + ) { return ch; } else { - throw new Error('Unexpected terminal'); + /* istanbul ignore next */ + throw new Error("Unexpected terminal"); } - } + }, }; diff --git a/src/lexer/scripting.js b/src/lexer/scripting.js index 943f6d0c5..0a6a1a1a3 100644 --- a/src/lexer/scripting.js +++ b/src/lexer/scripting.js @@ -1,100 +1,114 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; + module.exports = { - matchST_IN_SCRIPTING: function() { - var ch = this.input(); - switch(ch) { - case ' ': - case '\t': - case '\n': - case '\r': - case '\r\n': + matchST_IN_SCRIPTING: function () { + let ch = this.input(); + switch (ch) { + case " ": + case "\t": + case "\n": + case "\r": + case "\r\n": return this.T_WHITESPACE(); - case '#': + case "#": + if (this.version >= 800 && this._input[this.offset] === "[") { + this.input(); + this.attributeListDepth[++this.attributeIndex] = 0; + this.begin("ST_ATTRIBUTE"); + return this.tok.T_ATTRIBUTE; + } return this.T_COMMENT(); - case '/': - if (this._input[this.offset] === '/') { + case "/": + if (this._input[this.offset] === "/") { return this.T_COMMENT(); - } else if (this._input[this.offset] === '*') { + } else if (this._input[this.offset] === "*") { this.input(); return this.T_DOC_COMMENT(); } return this.consume_TOKEN(); - case '\'': + case "'": return this.T_CONSTANT_ENCAPSED_STRING(); case '"': return this.ST_DOUBLE_QUOTES(); - case '`': - this.begin('ST_BACKQUOTE'); - return '`'; - case '?': - if (!this.aspTagMode && this.tryMatch('>')) { + case "`": + this.begin("ST_BACKQUOTE"); + return "`"; + case "?": + if (!this.aspTagMode && this.tryMatch(">")) { this.input(); - var nextCH = this._input[this.offset]; - if (nextCH === '\n' || nextCH === '\r') this.input(); + const nextCH = this._input[this.offset]; + if (nextCH === "\n" || nextCH === "\r") this.input(); if (this.conditionStack.length > 1) { - this.begin('INITIAL'); + this.begin("INITIAL"); } return this.tok.T_CLOSE_TAG; } return this.consume_TOKEN(); - case '%': - if (this.aspTagMode && this._input[this.offset] === '>') { + case "%": + if (this.aspTagMode && this._input[this.offset] === ">") { this.input(); // consume the '>' ch = this._input[this.offset]; // read next - if (ch === '\n' || ch === '\r') { + if (ch === "\n" || ch === "\r") { this.input(); // consume the newline } this.aspTagMode = false; if (this.conditionStack.length > 1) { - this.begin('INITIAL'); + this.begin("INITIAL"); } return this.tok.T_CLOSE_TAG; } return this.consume_TOKEN(); - case '{': - this.begin('ST_IN_SCRIPTING'); - return '{'; - case '}': + case "{": + this.begin("ST_IN_SCRIPTING"); + return "{"; + case "}": if (this.conditionStack.length > 2) { // Return to HEREDOC/ST_DOUBLE_QUOTES mode this.popState(); } - return '}'; + return "}"; default: - if (ch === '.') { + if (ch === ".") { ch = this.input(); - if (this.is_NUM()) { + if (this.is_NUM_START()) { return this.consume_NUM(); } else { if (ch) this.unput(1); } } - if (this.is_NUM()) { + if (this.is_NUM_START()) { return this.consume_NUM(); } else if (this.is_LABEL_START()) { return this.consume_LABEL().T_STRING(); - } else if(this.is_TOKEN()) { + } else if (this.is_TOKEN()) { return this.consume_TOKEN(); } } throw new Error( - 'Bad terminal sequence "' + ch + '" at line ' + this.yylineno + ' (offset ' + this.offset + ')' + 'Bad terminal sequence "' + + ch + + '" at line ' + + this.yylineno + + " (offset " + + this.offset + + ")", ); }, - T_WHITESPACE: function() { - while(this.offset < this.size) { - var ch = this.input(); - if (ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r') { + T_WHITESPACE: function () { + while (this.offset < this.size) { + const ch = this.input(); + if (ch === " " || ch === "\t" || ch === "\n" || ch === "\r") { continue; } - this.unput(1); + if (ch) this.unput(1); break; } return this.tok.T_WHITESPACE; - } + }, }; diff --git a/src/lexer/strings.js b/src/lexer/strings.js index 14cad6ed0..689213e5f 100644 --- a/src/lexer/strings.js +++ b/src/lexer/strings.js @@ -1,35 +1,50 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; + +const newline = ["\n", "\r"]; +const valid_after_heredoc = ["\n", "\r", ";"]; +const valid_after_heredoc_73 = valid_after_heredoc.concat([ + "\t", + " ", + ",", + "]", + ")", + "/", + "=", + "!", +]); + module.exports = { - T_CONSTANT_ENCAPSED_STRING: function() { - var ch; - while(this.offset < this.size) { + T_CONSTANT_ENCAPSED_STRING: function () { + let ch; + while (this.offset < this.size) { ch = this.input(); - if (ch == '\\') { + if (ch == "\\") { this.input(); - } else if (ch == '\'') { + } else if (ch == "'") { break; } } return this.tok.T_CONSTANT_ENCAPSED_STRING; }, // check if matching a HEREDOC state - is_HEREDOC: function() { - var revert = this.offset; + is_HEREDOC: function () { + const revert = this.offset; if ( - this._input[this.offset - 1] === '<' - && this._input[this.offset] === '<' - && this._input[this.offset + 1] === '<' + this._input[this.offset - 1] === "<" && + this._input[this.offset] === "<" && + this._input[this.offset + 1] === "<" ) { this.offset += 3; // optional tabs / spaces if (this.is_TABSPACE()) { - while(this.offset < this.size) { - this.offset ++; + while (this.offset < this.size) { + this.offset++; if (!this.is_TABSPACE()) { break; } @@ -37,37 +52,42 @@ module.exports = { } // optional quotes - var tChar = this._input[this.offset - 1]; - if (tChar === '\'' || tChar === '"') { - this.offset ++; + let tChar = this._input[this.offset - 1]; + if (tChar === "'" || tChar === '"') { + this.offset++; } else { tChar = null; } // required label if (this.is_LABEL_START()) { - var yyoffset = this.offset - 1; - while(this.offset < this.size) { + let yyoffset = this.offset - 1; + while (this.offset < this.size) { this.offset++; if (!this.is_LABEL()) { break; } } - var yylabel = this._input.substring(yyoffset, this.offset - 1); - if (!tChar || tChar === this._input[this.offset - 1]) { // required ending quote - if (tChar) this.offset ++; + const yylabel = this._input.substring(yyoffset, this.offset - 1); + if (!tChar || tChar === this._input[this.offset - 1]) { + // required ending quote + if (tChar) this.offset++; // require newline - if (this._input[this.offset - 1] === '\r' || this._input[this.offset - 1] === '\n') { + if (newline.includes(this._input[this.offset - 1])) { // go go go - this.heredoc_label = yylabel; + this.heredoc_label.label = yylabel; + this.heredoc_label.length = yylabel.length; + this.heredoc_label.finished = false; yyoffset = this.offset - revert; this.offset = revert; this.consume(yyoffset); - if (tChar === '\'') { - this.begin('ST_NOWDOC'); + if (tChar === "'") { + this.begin("ST_NOWDOC"); } else { - this.begin('ST_HEREDOC'); + this.begin("ST_HEREDOC"); } + // prematch to get the indentation information from end of doc + this.prematch_ENDOFDOC(); return this.tok.T_START_HEREDOC; } } @@ -76,41 +96,41 @@ module.exports = { this.offset = revert; return false; }, - ST_DOUBLE_QUOTES: function() { - var ch; - while(this.offset < this.size) { + ST_DOUBLE_QUOTES: function () { + let ch; + while (this.offset < this.size) { ch = this.input(); - if (ch == '\\') { + if (ch == "\\") { this.input(); } else if (ch == '"') { break; - } else if (ch == '$') { + } else if (ch == "$") { ch = this.input(); - if ( ch == '{' || this.is_LABEL_START()) { + if (ch == "{" || this.is_LABEL_START()) { this.unput(2); break; } - this.unput(1); - } else if (ch == '{') { + if (ch) this.unput(1); + } else if (ch == "{") { ch = this.input(); - if (ch == '$') { + if (ch == "$") { this.unput(2); break; } - this.unput(1); + if (ch) this.unput(1); } } if (ch == '"') { return this.tok.T_CONSTANT_ENCAPSED_STRING; } else { - var prefix = 1; - if (this.yytext[0] === 'b' || this.yytext[0] === 'B') { + let prefix = 1; + if (this.yytext[0] === "b" || this.yytext[0] === "B") { prefix = 2; } if (this.yytext.length > 2) { this.appendToken( this.tok.T_ENCAPSED_AND_WHITESPACE, - this.yytext.length - prefix + this.yytext.length - prefix, ); } this.unput(this.yytext.length - prefix); @@ -120,38 +140,133 @@ module.exports = { }, // check if its a DOC end sequence - isDOC_MATCH: function() { + isDOC_MATCH: function (offset, consumeLeadingSpaces) { // @fixme : check if out of text limits - if (this._input.substring(this.offset - 1, this.offset - 1 + this.heredoc_label.length) === this.heredoc_label) { - var ch = this._input[this.offset - 1 + this.heredoc_label.length]; - if (ch === '\n' || ch === '\r' || ch === ';') { + + // consumeLeadingSpaces is false happen DOC prematch END HEREDOC stage. + + // Ensure current state is really after a new line break, not after a such as ${variables} + const prev_ch = this._input[offset - 2]; + if (!newline.includes(prev_ch)) { + return false; + } + + // skip leading spaces or tabs + let indentation_uses_spaces = false; + let indentation_uses_tabs = false; + // reset heredoc_label structure + let indentation = 0; + let leading_ch = this._input[offset - 1]; + + if (this.version >= 703) { + while (leading_ch === "\t" || leading_ch === " ") { + if (leading_ch === " ") { + indentation_uses_spaces = true; + } else if (leading_ch === "\t") { + indentation_uses_tabs = true; + } + + leading_ch = this._input[offset + indentation]; + indentation++; + } + + // Move offset to skip leading whitespace + offset = offset + indentation; + + // return out if there was only whitespace on this line + if (newline.includes(this._input[offset - 1])) { + return false; + } + } + + if ( + this._input.substring( + offset - 1, + offset - 1 + this.heredoc_label.length, + ) === this.heredoc_label.label + ) { + const ch = this._input[offset - 1 + this.heredoc_label.length]; + if ( + (this.version >= 703 + ? valid_after_heredoc_73 + : valid_after_heredoc + ).includes(ch) + ) { + if (consumeLeadingSpaces) { + this.consume(indentation); + // https://wiki.php.net/rfc/flexible_heredoc_nowdoc_syntaxes + if (indentation_uses_spaces && indentation_uses_tabs) { + throw new Error( + "Parse error: mixing spaces and tabs in ending marker at line " + + this.yylineno + + " (offset " + + this.offset + + ")", + ); + } + } else { + // Called in prematch_ENDOFDOC + this.heredoc_label.indentation = indentation; + this.heredoc_label.indentation_uses_spaces = indentation_uses_spaces; + this.heredoc_label.first_encaps_node = true; + } return true; } } + return false; }, - matchST_NOWDOC: function() { - /** edge case : empty now doc **/ - if (this.isDOC_MATCH()) { + /* + * Prematch the end of HEREDOC/NOWDOC end tag to preset the + * context of this.heredoc_label + */ + prematch_ENDOFDOC: function () { + // reset heredoc + this.heredoc_label.indentation_uses_spaces = false; + this.heredoc_label.indentation = 0; + this.heredoc_label.first_encaps_node = true; + let offset = this.offset + 1; + + while (offset < this._input.length) { + // if match heredoc_label structrue will be set + if (this.isDOC_MATCH(offset, false)) { + return; + } + + if (!newline.includes(this._input[offset - 1])) { + // skip one line + while ( + !newline.includes(this._input[offset++]) && + offset < this._input.length + ) { + // skip + } + } + + offset++; + } + }, + + matchST_NOWDOC: function () { + // edge case : empty now doc + if (this.isDOC_MATCH(this.offset, true)) { // @fixme : never reached (may be caused by quotes) this.consume(this.heredoc_label.length); this.popState(); return this.tok.T_END_HEREDOC; } - /** SCANNING CONTENTS **/ - var ch = this._input[this.offset - 1]; - while(this.offset < this.size) { - if (ch === '\n' || ch === '\r') { + // SCANNING CONTENTS + let ch = this._input[this.offset - 1]; + while (this.offset < this.size) { + if (newline.includes(ch)) { ch = this.input(); - if (this.isDOC_MATCH()) { + if (this.isDOC_MATCH(this.offset, true)) { this.unput(1).popState(); - this.appendToken( - this.tok.T_END_HEREDOC, this.heredoc_label.length - ); + this.appendToken(this.tok.T_END_HEREDOC, this.heredoc_label.length); return this.tok.T_ENCAPSED_AND_WHITESPACE; } - } else { + } else { ch = this.input(); } } @@ -159,49 +274,46 @@ module.exports = { return this.tok.T_ENCAPSED_AND_WHITESPACE; }, - matchST_HEREDOC: function() { - /** edge case : empty here doc **/ - var ch = this.input(); - if (this.isDOC_MATCH()) { + matchST_HEREDOC: function () { + // edge case : empty here doc + let ch = this.input(); + if (this.isDOC_MATCH(this.offset, true)) { this.consume(this.heredoc_label.length - 1); this.popState(); return this.tok.T_END_HEREDOC; } - /** SCANNING CONTENTS **/ - while(this.offset < this.size) { - - if (ch === '\\') { + // SCANNING CONTENTS + while (this.offset < this.size) { + if (ch === "\\") { ch = this.input(); // ignore next - if (ch !== '\n' && ch !== '\r') { + if (!newline.includes(ch)) { ch = this.input(); } } - if (ch === '\n' || ch === '\r') { + if (newline.includes(ch)) { ch = this.input(); - if (this.isDOC_MATCH()) { + if (this.isDOC_MATCH(this.offset, true)) { this.unput(1).popState(); - this.appendToken( - this.tok.T_END_HEREDOC, this.heredoc_label.length - ); + this.appendToken(this.tok.T_END_HEREDOC, this.heredoc_label.length); return this.tok.T_ENCAPSED_AND_WHITESPACE; } - } else if (ch === '$') { + } else if (ch === "$") { ch = this.input(); - if (ch === '{') { + if (ch === "{") { // start of ${ - this.begin('ST_LOOKING_FOR_VARNAME'); + this.begin("ST_LOOKING_FOR_VARNAME"); if (this.yytext.length > 2) { this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2); this.unput(2); return this.tok.T_ENCAPSED_AND_WHITESPACE; - }else { + } else { return this.tok.T_DOLLAR_OPEN_CURLY_BRACES; } } else if (this.is_LABEL_START()) { // start of $var... - var yyoffset = this.offset; - var next = this.consume_VARIABLE(); + const yyoffset = this.offset; + const next = this.consume_VARIABLE(); if (this.yytext.length > this.offset - yyoffset + 2) { this.appendToken(next, this.offset - yyoffset + 2); this.unput(this.offset - yyoffset + 2); @@ -211,11 +323,11 @@ module.exports = { } //console.log(this.yytext); } - } else if (ch === '{') { + } else if (ch === "{") { ch = this.input(); - if (ch === '$') { + if (ch === "$") { // start of {$... - this.begin('ST_IN_SCRIPTING'); + this.begin("ST_IN_SCRIPTING"); if (this.yytext.length > 2) { this.appendToken(this.tok.T_CURLY_OPEN, 1); this.unput(2); @@ -234,76 +346,75 @@ module.exports = { return this.tok.T_ENCAPSED_AND_WHITESPACE; }, - consume_VARIABLE: function() { + consume_VARIABLE: function () { this.consume_LABEL(); - ch = this.input(); - if (ch == '[') { + const ch = this.input(); + if (ch == "[") { this.unput(1); - this.begin('ST_VAR_OFFSET'); + this.begin("ST_VAR_OFFSET"); return this.tok.T_VARIABLE; - } else if (ch === '-') { - if (this.input() === '>') { + } else if (ch === "-") { + if (this.input() === ">") { this.input(); if (this.is_LABEL_START()) { - this.begin('ST_LOOKING_FOR_PROPERTY'); + this.begin("ST_LOOKING_FOR_PROPERTY"); } this.unput(3); return this.tok.T_VARIABLE; } else { this.unput(2); } - } else { - this.unput(1); - } - return this.tok.T_VARIABLE; + } else { + if (ch) this.unput(1); + } + return this.tok.T_VARIABLE; }, // HANDLES BACKQUOTES - matchST_BACKQUOTE: function() { - - var ch = this.input(); - if (ch === '$') { + matchST_BACKQUOTE: function () { + let ch = this.input(); + if (ch === "$") { ch = this.input(); - if (ch === '{') { - this.begin('ST_LOOKING_FOR_VARNAME'); + if (ch === "{") { + this.begin("ST_LOOKING_FOR_VARNAME"); return this.tok.T_DOLLAR_OPEN_CURLY_BRACES; } else if (this.is_LABEL_START()) { - var tok = this.consume_VARIABLE(); + const tok = this.consume_VARIABLE(); return tok; } - } else if (ch === '{') { - if (this._input[this.offset] === '$') { - this.begin('ST_IN_SCRIPTING'); + } else if (ch === "{") { + if (this._input[this.offset] === "$") { + this.begin("ST_IN_SCRIPTING"); return this.tok.T_CURLY_OPEN; } - } else if (ch === '`') { + } else if (ch === "`") { this.popState(); - return '`'; + return "`"; } // any char - while(this.offset < this.size) { - if (ch === '\\') { + while (this.offset < this.size) { + if (ch === "\\") { this.input(); - } else if (ch === '`') { + } else if (ch === "`") { this.unput(1); this.popState(); - this.appendToken('`', 1); + this.appendToken("`", 1); break; - } else if (ch === '$') { + } else if (ch === "$") { ch = this.input(); - if (ch === '{') { - this.begin('ST_LOOKING_FOR_VARNAME'); + if (ch === "{") { + this.begin("ST_LOOKING_FOR_VARNAME"); if (this.yytext.length > 2) { this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2); this.unput(2); return this.tok.T_ENCAPSED_AND_WHITESPACE; - }else { + } else { return this.tok.T_DOLLAR_OPEN_CURLY_BRACES; } } else if (this.is_LABEL_START()) { // start of $var... - var yyoffset = this.offset; - var next = this.consume_VARIABLE(); + const yyoffset = this.offset; + const next = this.consume_VARIABLE(); if (this.yytext.length > this.offset - yyoffset + 2) { this.appendToken(next, this.offset - yyoffset + 2); this.unput(this.offset - yyoffset + 2); @@ -312,12 +423,12 @@ module.exports = { return next; } } - this.unput(1); - } else if (ch === '{') { + continue; + } else if (ch === "{") { ch = this.input(); - if (ch === '$') { + if (ch === "$") { // start of {$... - this.begin('ST_IN_SCRIPTING'); + this.begin("ST_IN_SCRIPTING"); if (this.yytext.length > 2) { this.appendToken(this.tok.T_CURLY_OPEN, 1); this.unput(2); @@ -327,29 +438,27 @@ module.exports = { return this.tok.T_CURLY_OPEN; } } - this.unput(1); + continue; } ch = this.input(); } return this.tok.T_ENCAPSED_AND_WHITESPACE; - }, - matchST_DOUBLE_QUOTES: function() { - - var ch = this.input(); - if (ch === '$') { + matchST_DOUBLE_QUOTES: function () { + let ch = this.input(); + if (ch === "$") { ch = this.input(); - if (ch === '{') { - this.begin('ST_LOOKING_FOR_VARNAME'); + if (ch === "{") { + this.begin("ST_LOOKING_FOR_VARNAME"); return this.tok.T_DOLLAR_OPEN_CURLY_BRACES; } else if (this.is_LABEL_START()) { - var tok = this.consume_VARIABLE(); + const tok = this.consume_VARIABLE(); return tok; } - } else if (ch === '{') { - if (this._input[this.offset] === '$') { - this.begin('ST_IN_SCRIPTING'); + } else if (ch === "{") { + if (this._input[this.offset] === "$") { + this.begin("ST_IN_SCRIPTING"); return this.tok.T_CURLY_OPEN; } } else if (ch === '"') { @@ -358,29 +467,29 @@ module.exports = { } // any char - while(this.offset < this.size) { - if (ch === '\\') { + while (this.offset < this.size) { + if (ch === "\\") { this.input(); } else if (ch === '"') { this.unput(1); this.popState(); this.appendToken('"', 1); break; - } else if (ch === '$') { + } else if (ch === "$") { ch = this.input(); - if (ch === '{') { - this.begin('ST_LOOKING_FOR_VARNAME'); + if (ch === "{") { + this.begin("ST_LOOKING_FOR_VARNAME"); if (this.yytext.length > 2) { this.appendToken(this.tok.T_DOLLAR_OPEN_CURLY_BRACES, 2); this.unput(2); return this.tok.T_ENCAPSED_AND_WHITESPACE; - }else { + } else { return this.tok.T_DOLLAR_OPEN_CURLY_BRACES; } } else if (this.is_LABEL_START()) { // start of $var... - var yyoffset = this.offset; - var next = this.consume_VARIABLE(); + const yyoffset = this.offset; + const next = this.consume_VARIABLE(); if (this.yytext.length > this.offset - yyoffset + 2) { this.appendToken(next, this.offset - yyoffset + 2); this.unput(this.offset - yyoffset + 2); @@ -389,12 +498,12 @@ module.exports = { return next; } } - this.unput(1); - } else if (ch === '{') { + if (ch) this.unput(1); + } else if (ch === "{") { ch = this.input(); - if (ch === '$') { + if (ch === "$") { // start of {$... - this.begin('ST_IN_SCRIPTING'); + this.begin("ST_IN_SCRIPTING"); if (this.yytext.length > 2) { this.appendToken(this.tok.T_CURLY_OPEN, 1); this.unput(2); @@ -410,5 +519,5 @@ module.exports = { ch = this.input(); } return this.tok.T_ENCAPSED_AND_WHITESPACE; - } + }, }; diff --git a/src/lexer/tokens.js b/src/lexer/tokens.js index 07da431a4..217524ca8 100644 --- a/src/lexer/tokens.js +++ b/src/lexer/tokens.js @@ -1,15 +1,17 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; + module.exports = { - T_STRING: function() { - var token = this.yytext.toLowerCase(); - var id = this.keywords[token]; - if (!id) { - if (token === 'yield') { - if (this.tryMatch(' from')) { + T_STRING: function () { + const token = this.yytext.toLowerCase(); + let id = this.keywords[token]; + if (typeof id !== "number") { + if (token === "yield") { + if (this.version >= 700 && this.tryMatch(" from")) { this.consume(5); id = this.tok.T_YIELD_FROM; } else { @@ -17,11 +19,11 @@ module.exports = { } } else { id = this.tok.T_STRING; - if (token === 'b' || token === 'B') { - var ch = this.input(1); + if (token === "b" || token === "B") { + const ch = this.input(); if (ch === '"') { return this.ST_DOUBLE_QUOTES(); - } else if (ch === '\'') { + } else if (ch === "'") { return this.T_CONSTANT_ENCAPSED_STRING(); } else if (ch) { this.unput(1); @@ -29,12 +31,61 @@ module.exports = { } } } + + // https://github.com/php/php-src/blob/master/Zend/zend_language_scanner.l#L1546 + if (id === this.tok.T_ENUM) { + if (this.version < 801) { + return this.tok.T_STRING; + } + const initial = this.offset; + let ch = this.input(); + while (ch == " ") { + ch = this.input(); + } + let isEnum = false; + if (this.is_LABEL_START()) { + while (this.is_LABEL()) { + ch += this.input(); + } + const label = ch.slice(0, -1).toLowerCase(); + isEnum = label !== "extends" && label !== "implements"; + } + + this.unput(this.offset - initial); + return isEnum ? this.tok.T_ENUM : this.tok.T_STRING; + } + + if (this.offset < this.size && id !== this.tok.T_YIELD_FROM) { + // If immediately followed by a backslash, this is a T_NAME_RELATIVE or T_NAME_QUALIFIED. + let ch = this.input(); + if (ch === "\\") { + id = + token === "namespace" + ? this.tok.T_NAME_RELATIVE + : this.tok.T_NAME_QUALIFIED; + do { + if (this._input[this.offset] === "{") { + // e.g. when using group use statements, the last '\\' is followed by a '{' + this.input(); + break; + } + + this.consume_LABEL(); + ch = this.input(); + } while (ch === "\\"); + } + + if (ch) { + this.unput(1); + } + } + return id; }, // reads a custom token - consume_TOKEN: function() { - var ch = this._input[this.offset - 1]; - var fn = this.tokenTerminals[ch]; + consume_TOKEN: function () { + const ch = this._input[this.offset - 1]; + const fn = this.tokenTerminals[ch]; if (fn) { return fn.apply(this, []); } else { @@ -43,7 +94,7 @@ module.exports = { }, // list of special char tokens tokenTerminals: { - '$': function() { + $: function () { this.offset++; if (this.is_LABEL_START()) { this.offset--; @@ -51,73 +102,95 @@ module.exports = { return this.tok.T_VARIABLE; } else { this.offset--; - return '$'; + return "$"; } }, - '-': function() { - var nchar = this._input[this.offset]; - if (nchar === '>') { - this.begin('ST_LOOKING_FOR_PROPERTY').input(); + "-": function () { + const nchar = this._input[this.offset]; + if (nchar === ">") { + this.begin("ST_LOOKING_FOR_PROPERTY").input(); return this.tok.T_OBJECT_OPERATOR; - } else if (nchar === '-') { + } else if (nchar === "-") { this.input(); return this.tok.T_DEC; - } else if (nchar === '=') { + } else if (nchar === "=") { this.input(); return this.tok.T_MINUS_EQUAL; } - return '-'; + return "-"; }, - '\\': function() { + "\\": function () { + if (this.offset < this.size) { + this.input(); + if (this.is_LABEL_START()) { + let ch; + do { + if (this._input[this.offset] === "{") { + // e.g. when using group use statements, the last '\\' is followed by a '{' + this.input(); + break; + } + + this.consume_LABEL(); + ch = this.input(); + } while (ch === "\\"); + + this.unput(1); + + return this.tok.T_NAME_FULLY_QUALIFIED; + } else { + this.unput(1); + } + } return this.tok.T_NS_SEPARATOR; }, - '/': function() { - if (this._input[this.offset] === '=') { + "/": function () { + if (this._input[this.offset] === "=") { this.input(); return this.tok.T_DIV_EQUAL; } - return '/'; + return "/"; }, - ':': function() { - if (this._input[this.offset] === ':') { + ":": function () { + if (this._input[this.offset] === ":") { this.input(); return this.tok.T_DOUBLE_COLON; } else { - return ':'; + return ":"; } }, - '(': function() { - var initial = this.offset; + "(": function () { + const initial = this.offset; this.input(); if (this.is_TABSPACE()) { this.consume_TABSPACE().input(); } if (this.is_LABEL_START()) { - var yylen = this.yytext.length; + const yylen = this.yytext.length; this.consume_LABEL(); - var castToken = this.yytext.substring(yylen - 1).toLowerCase(); - var castId = this.castKeywords[castToken]; - if (castId) { + const castToken = this.yytext.substring(yylen - 1).toLowerCase(); + const castId = this.castKeywords[castToken]; + if (typeof castId === "number") { this.input(); if (this.is_TABSPACE()) { this.consume_TABSPACE().input(); } - if (this._input[this.offset - 1] === ')') { + if (this._input[this.offset - 1] === ")") { return castId; } } } // revert the check this.unput(this.offset - initial); - return '('; + return "("; }, - '=': function() { - var nchar = this._input[this.offset]; - if (nchar === '>') { + "=": function () { + const nchar = this._input[this.offset]; + if (nchar === ">") { this.input(); return this.tok.T_DOUBLE_ARROW; - } else if (nchar === '=') { - if (this._input[this.offset + 1] === '=') { + } else if (nchar === "=") { + if (this._input[this.offset + 1] === "=") { this.consume(2); return this.tok.T_IS_IDENTICAL; } else { @@ -125,22 +198,22 @@ module.exports = { return this.tok.T_IS_EQUAL; } } - return '='; + return "="; }, - '+': function() { - var nchar = this._input[this.offset]; - if (nchar === '+') { + "+": function () { + const nchar = this._input[this.offset]; + if (nchar === "+") { this.input(); return this.tok.T_INC; - } else if (nchar === '=') { + } else if (nchar === "=") { this.input(); return this.tok.T_PLUS_EQUAL; } - return '+'; + return "+"; }, - '!': function() { - if (this._input[this.offset] === '=') { - if (this._input[this.offset + 1] === '=') { + "!": function () { + if (this._input[this.offset] === "=") { + if (this._input[this.offset + 1] === "=") { this.consume(2); return this.tok.T_IS_NOT_IDENTICAL; } else { @@ -148,51 +221,65 @@ module.exports = { return this.tok.T_IS_NOT_EQUAL; } } - return '!'; + return "!"; }, - '?': function() { - if (this._input[this.offset] === '?') { - this.input(); - return this.tok.T_COALESCE; + "?": function () { + if (this.version >= 700 && this._input[this.offset] === "?") { + if (this.version >= 704 && this._input[this.offset + 1] === "=") { + this.consume(2); + return this.tok.T_COALESCE_EQUAL; + } else { + this.input(); + return this.tok.T_COALESCE; + } + } + if ( + this.version >= 800 && + this._input[this.offset] === "-" && + this._input[this.offset + 1] === ">" + ) { + this.consume(1); + this.begin("ST_LOOKING_FOR_PROPERTY").input(); + return this.tok.T_NULLSAFE_OBJECT_OPERATOR; } - return '?'; + return "?"; }, - '<': function() { - var nchar = this._input[this.offset]; - if (nchar === '<') { + "<": function () { + let nchar = this._input[this.offset]; + if (nchar === "<") { nchar = this._input[this.offset + 1]; - if (nchar === '=') { + if (nchar === "=") { this.consume(2); return this.tok.T_SL_EQUAL; - } else if (nchar === '<') { + } else if (nchar === "<") { if (this.is_HEREDOC()) { return this.tok.T_START_HEREDOC; } } this.input(); return this.tok.T_SL; - } else if (nchar === '=') { + } else if (nchar === "=") { this.input(); - if (this._input[this.offset] === '>') { + if (this.version >= 700 && this._input[this.offset] === ">") { this.input(); return this.tok.T_SPACESHIP; } else { return this.tok.T_IS_SMALLER_OR_EQUAL; } - } else if (nchar === '>') { + } else if (nchar === ">") { this.input(); return this.tok.T_IS_NOT_EQUAL; } - return '<'; + return "<"; }, - '>': function() { - var nchar = this._input[this.offset]; - if (nchar === '=') { + ">": function () { + let nchar = this._input[this.offset]; + if (nchar === "=") { this.input(); return this.tok.T_IS_GREATER_OR_EQUAL; - } else if (nchar === '>') { + } else if (nchar === ">") { nchar = this._input[this.offset + 1]; - if (nchar === '=') { + if (nchar === "=") { this.consume(2); return this.tok.T_SR_EQUAL; } else { @@ -200,70 +287,70 @@ module.exports = { return this.tok.T_SR; } } - return '>'; + return ">"; }, - '*': function() { - var nchar = this._input[this.offset]; - if (nchar === '=') { + "*": function () { + const nchar = this._input[this.offset]; + if (nchar === "=") { this.input(); return this.tok.T_MUL_EQUAL; - } else if(nchar === '*') { + } else if (nchar === "*") { this.input(); - if (this._input[this.offset] === '=') { + if (this._input[this.offset] === "=") { this.input(); return this.tok.T_POW_EQUAL; } else { return this.tok.T_POW; } } - return '*'; + return "*"; }, - '.': function() { - var nchar = this._input[this.offset]; - if (nchar === '=') { + ".": function () { + const nchar = this._input[this.offset]; + if (nchar === "=") { this.input(); return this.tok.T_CONCAT_EQUAL; - } else if (nchar === '.' && this._input[this.offset + 1] === '.') { + } else if (nchar === "." && this._input[this.offset + 1] === ".") { this.consume(2); return this.tok.T_ELLIPSIS; } - return '.'; + return "."; }, - '%': function() { - if (this._input[this.offset] === '=') { + "%": function () { + if (this._input[this.offset] === "=") { this.input(); return this.tok.T_MOD_EQUAL; } - return '%'; + return "%"; }, - '&': function() { - var nchar = this._input[this.offset]; - if (nchar === '=') { + "&": function () { + const nchar = this._input[this.offset]; + if (nchar === "=") { this.input(); return this.tok.T_AND_EQUAL; - } else if (nchar === '&') { + } else if (nchar === "&") { this.input(); return this.tok.T_BOOLEAN_AND; } - return '&'; + return "&"; }, - '|': function() { - var nchar = this._input[this.offset]; - if (nchar === '=') { + "|": function () { + const nchar = this._input[this.offset]; + if (nchar === "=") { this.input(); return this.tok.T_OR_EQUAL; - } else if (nchar === '|') { + } else if (nchar === "|") { this.input(); return this.tok.T_BOOLEAN_OR; } - return '|'; + return "|"; }, - '^': function() { - if (this._input[this.offset] === '=') { + "^": function () { + if (this._input[this.offset] === "=") { this.input(); return this.tok.T_XOR_EQUAL; } - return '^'; - } - } + return "^"; + }, + }, }; diff --git a/src/lexer/utils.js b/src/lexer/utils.js index 5d311a1d1..8a2733037 100644 --- a/src/lexer/utils.js +++ b/src/lexer/utils.js @@ -1,46 +1,58 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ - var tokens = ';:,.\\[]()|^&+-/*=%!~$<>?@'; +"use strict"; + +const tokens = ";:,.\\[]()|^&+-/*=%!~$<>?@"; module.exports = { + // check if the char can be a numeric + is_NUM: function () { + const ch = this._input.charCodeAt(this.offset - 1); + return (ch > 47 && ch < 58) || ch === 95; + }, // check if the char can be a numeric - is_NUM: function() { - var ch = this._input.charCodeAt(this.offset - 1); + is_NUM_START: function () { + const ch = this._input.charCodeAt(this.offset - 1); return ch > 47 && ch < 58; }, // check if current char can be a label - is_LABEL: function() { - var ch = this._input.charCodeAt(this.offset - 1); - return (ch > 96 && ch < 123) - || (ch > 64 && ch < 91) - || ch === 95 - || (ch > 47 && ch < 58) - || ch > 126 - ; + is_LABEL: function () { + const ch = this._input.charCodeAt(this.offset - 1); + return ( + (ch > 96 && ch < 123) || + (ch > 64 && ch < 91) || + ch === 95 || + (ch > 47 && ch < 58) || + ch > 126 + ); }, // check if current char can be a label - is_LABEL_START: function() { - var ch = this._input.charCodeAt(this.offset - 1); - return (ch > 96 && ch < 123) - || (ch > 64 && ch < 91) - || ch === 95 - || (ch > 126) - ; + is_LABEL_START: function () { + const ch = this._input.charCodeAt(this.offset - 1); + // A - Z + if (ch > 64 && ch < 91) return true; + // a - z + if (ch > 96 && ch < 123) return true; + // _ (95) + if (ch === 95) return true; + // utf8 / extended + if (ch > 126) return true; + // else + return false; }, - // reads each char of the label - consume_LABEL: function() { - while(this.offset < this.size) { - this.input(); + consume_LABEL: function () { + while (this.offset < this.size) { + const ch = this.input(); if (!this.is_LABEL()) { - this.unput(1); + if (ch) this.unput(1); break; } } @@ -48,34 +60,53 @@ module.exports = { }, // check if current char is a token char - is_TOKEN: function() { - var ch = this._input[this.offset - 1]; + is_TOKEN: function () { + const ch = this._input[this.offset - 1]; return tokens.indexOf(ch) !== -1; }, // check if current char is a whitespace - is_WHITESPACE: function() { - var ch = this._input[this.offset - 1]; - return ch === ' ' || ch === '\t' || ch === '\n' || ch === '\r'; + is_WHITESPACE: function () { + const ch = this._input[this.offset - 1]; + return ch === " " || ch === "\t" || ch === "\n" || ch === "\r"; }, // check if current char is a whitespace (without newlines) - is_TABSPACE: function() { - var ch = this._input[this.offset - 1]; - return ch === ' ' || ch === '\t'; + is_TABSPACE: function () { + const ch = this._input[this.offset - 1]; + return ch === " " || ch === "\t"; }, // consume all whitespaces (excluding newlines) - consume_TABSPACE: function() { - while(this.offset < this.size) { - this.input(); + consume_TABSPACE: function () { + while (this.offset < this.size) { + const ch = this.input(); if (!this.is_TABSPACE()) { - this.unput(1); + if (ch) this.unput(1); break; } } return this; }, // check if current char can be a hexadecimal number - is_HEX: function() { - var ch = this._input.charCodeAt(this.offset - 1); - return (ch > 47 && ch < 58) || (ch > 64 && ch < 71) || (ch > 96 && ch < 103); - } + is_HEX: function () { + const ch = this._input.charCodeAt(this.offset - 1); + // 0 - 9 + if (ch > 47 && ch < 58) return true; + // A - F + if (ch > 64 && ch < 71) return true; + // a - f + if (ch > 96 && ch < 103) return true; + // _ (code 95) + if (ch === 95) return true; + // else + return false; + }, + // check if current char can be an octal number + is_OCTAL: function () { + const ch = this._input.charCodeAt(this.offset - 1); + // 0 - 7 + if (ch > 47 && ch < 56) return true; + // _ (code 95) + if (ch === 95) return true; + // else + return false; + }, }; diff --git a/src/parser.js b/src/parser.js index 02f5554a6..5e5ef1fa5 100644 --- a/src/parser.js +++ b/src/parser.js @@ -1,28 +1,34 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; + +const Position = require("./ast/position"); /** - * @private check if argument is a number + * @private */ function isNumber(n) { - return n != '.' && n != ',' && !isNaN(parseFloat(n)) && isFinite(n); + return n != "." && n != "," && !isNaN(parseFloat(n)) && isFinite(n); } - /** * The PHP Parser class that build the AST tree from the lexer - * @constructor {Parser} + * + * @constructor Parser + * @memberOf module:php-parser + * @tutorial Parser * @property {Lexer} lexer - current lexer instance * @property {AST} ast - the AST factory instance - * @property {Integer|String} token - current token - * @property {Boolean} extractDoc - should extract documentation as AST node - * @property {Boolean} suppressErrors - should ignore parsing errors and continue - * @property {Boolean} debug - should output debug informations + * @property {number|string} token - current token + * @property {boolean} extractDoc - should extract documentation as AST node + * @property {boolean} extractTokens - should extract each token + * @property {boolean} suppressErrors - should ignore parsing errors and continue + * @property {boolean} debug - should output debug informations */ -var parser = function(lexer, ast) { +const Parser = function (lexer, ast) { this.lexer = lexer; this.ast = ast; this.tok = lexer.tok; @@ -30,38 +36,205 @@ var parser = function(lexer, ast) { this.token = null; this.prev = null; this.debug = false; + this.version = 803; this.extractDoc = false; + this.extractTokens = false; this.suppressErrors = false; + const mapIt = function (item) { + return [item, null]; + }; this.entries = { - 'VARIABLE': [ - this.tok.T_VARIABLE, - '$', '&', - this.tok.T_NS_SEPARATOR, - this.tok.T_STRING, - this.tok.T_NAMESPACE, - this.tok.T_STATIC - ], - 'SCALAR': [ - this.tok.T_CONSTANT_ENCAPSED_STRING, - this.tok.T_START_HEREDOC, - this.tok.T_LNUMBER, - this.tok.T_DNUMBER, - this.tok.T_ARRAY,'[', - this.tok.T_CLASS_C, - this.tok.T_TRAIT_C, - this.tok.T_FUNC_C, - this.tok.T_METHOD_C, - this.tok.T_LINE, - this.tok.T_FILE, - this.tok.T_DIR, - this.tok.T_NS_C, - '"', - 'b"', - 'B"', - '-', - this.tok.T_NS_SEPARATOR - ], - 'T_MAGIC_CONST': [ + // reserved_non_modifiers + IDENTIFIER: new Map( + [ + this.tok.T_ABSTRACT, + this.tok.T_ARRAY, + this.tok.T_AS, + this.tok.T_BREAK, + this.tok.T_CALLABLE, + this.tok.T_CASE, + this.tok.T_CATCH, + this.tok.T_CLASS, + this.tok.T_CLASS_C, + this.tok.T_CLONE, + this.tok.T_CONST, + this.tok.T_CONTINUE, + this.tok.T_DECLARE, + this.tok.T_DEFAULT, + this.tok.T_DIR, + this.tok.T_DO, + this.tok.T_ECHO, + this.tok.T_ELSE, + this.tok.T_ELSEIF, + this.tok.T_EMPTY, + this.tok.T_ENDDECLARE, + this.tok.T_ENDFOR, + this.tok.T_ENDFOREACH, + this.tok.T_ENDIF, + this.tok.T_ENDSWITCH, + this.tok.T_ENDWHILE, + this.tok.T_ENUM, + this.tok.T_EVAL, + this.tok.T_EXIT, + this.tok.T_EXTENDS, + this.tok.T_FILE, + this.tok.T_FINAL, + this.tok.T_FINALLY, + this.tok.T_FN, + this.tok.T_FOR, + this.tok.T_FOREACH, + this.tok.T_FUNC_C, + this.tok.T_FUNCTION, + this.tok.T_GLOBAL, + this.tok.T_GOTO, + this.tok.T_IF, + this.tok.T_IMPLEMENTS, + this.tok.T_INCLUDE, + this.tok.T_INCLUDE_ONCE, + this.tok.T_INSTANCEOF, + this.tok.T_INSTEADOF, + this.tok.T_INTERFACE, + this.tok.T_ISSET, + this.tok.T_LINE, + this.tok.T_LIST, + this.tok.T_LOGICAL_AND, + this.tok.T_LOGICAL_OR, + this.tok.T_LOGICAL_XOR, + this.tok.T_MATCH, + this.tok.T_METHOD_C, + this.tok.T_NAMESPACE, + this.tok.T_NEW, + this.tok.T_NS_C, + this.tok.T_PRINT, + this.tok.T_PRIVATE, + this.tok.T_PROTECTED, + this.tok.T_PUBLIC, + this.tok.T_READ_ONLY, + this.tok.T_REQUIRE, + this.tok.T_REQUIRE_ONCE, + this.tok.T_RETURN, + this.tok.T_STATIC, + this.tok.T_SWITCH, + this.tok.T_THROW, + this.tok.T_TRAIT, + this.tok.T_TRY, + this.tok.T_UNSET, + this.tok.T_USE, + this.tok.T_VAR, + this.tok.T_WHILE, + this.tok.T_YIELD, + ].map(mapIt), + ), + VARIABLE: new Map( + [ + this.tok.T_VARIABLE, + "$", + "&", + this.tok.T_STRING, + this.tok.T_NAME_RELATIVE, + this.tok.T_NAME_QUALIFIED, + this.tok.T_NAME_FULLY_QUALIFIED, + this.tok.T_NAMESPACE, + this.tok.T_STATIC, + ].map(mapIt), + ), + SCALAR: new Map( + [ + this.tok.T_CONSTANT_ENCAPSED_STRING, + this.tok.T_START_HEREDOC, + this.tok.T_LNUMBER, + this.tok.T_DNUMBER, + this.tok.T_ARRAY, + "[", + this.tok.T_CLASS_C, + this.tok.T_TRAIT_C, + this.tok.T_FUNC_C, + this.tok.T_METHOD_C, + this.tok.T_LINE, + this.tok.T_FILE, + this.tok.T_DIR, + this.tok.T_NS_C, + '"', + 'b"', + 'B"', + "-", + this.tok.T_NS_SEPARATOR, + ].map(mapIt), + ), + T_MAGIC_CONST: new Map( + [ + this.tok.T_CLASS_C, + this.tok.T_TRAIT_C, + this.tok.T_FUNC_C, + this.tok.T_METHOD_C, + this.tok.T_LINE, + this.tok.T_FILE, + this.tok.T_DIR, + this.tok.T_NS_C, + ].map(mapIt), + ), + T_MEMBER_FLAGS: new Map( + [ + this.tok.T_PUBLIC, + this.tok.T_PRIVATE, + this.tok.T_PROTECTED, + this.tok.T_STATIC, + this.tok.T_ABSTRACT, + this.tok.T_FINAL, + ].map(mapIt), + ), + EOS: new Map([";", this.EOF, this.tok.T_INLINE_HTML].map(mapIt)), + EXPR: new Map( + [ + "@", + "-", + "+", + "!", + "~", + "(", + "`", + this.tok.T_LIST, + this.tok.T_CLONE, + this.tok.T_INC, + this.tok.T_DEC, + this.tok.T_NEW, + this.tok.T_ISSET, + this.tok.T_EMPTY, + this.tok.T_MATCH, + this.tok.T_INCLUDE, + this.tok.T_INCLUDE_ONCE, + this.tok.T_REQUIRE, + this.tok.T_REQUIRE_ONCE, + this.tok.T_EVAL, + this.tok.T_INT_CAST, + this.tok.T_DOUBLE_CAST, + this.tok.T_STRING_CAST, + this.tok.T_ARRAY_CAST, + this.tok.T_OBJECT_CAST, + this.tok.T_BOOL_CAST, + this.tok.T_UNSET_CAST, + this.tok.T_EXIT, + this.tok.T_PRINT, + this.tok.T_YIELD, + this.tok.T_STATIC, + this.tok.T_FUNCTION, + this.tok.T_FN, + // using VARIABLES : + this.tok.T_VARIABLE, + "$", + this.tok.T_NS_SEPARATOR, + this.tok.T_STRING, + this.tok.T_NAME_RELATIVE, + this.tok.T_NAME_QUALIFIED, + this.tok.T_NAME_FULLY_QUALIFIED, + // using SCALAR : + this.tok.T_STRING, // @see variable.js line 45 > conflict with variable = shift/reduce :) + this.tok.T_CONSTANT_ENCAPSED_STRING, + this.tok.T_START_HEREDOC, + this.tok.T_LNUMBER, + this.tok.T_DNUMBER, + this.tok.T_ARRAY, + "[", this.tok.T_CLASS_C, this.tok.T_TRAIT_C, this.tok.T_FUNC_C, @@ -69,128 +242,126 @@ var parser = function(lexer, ast) { this.tok.T_LINE, this.tok.T_FILE, this.tok.T_DIR, - this.tok.T_NS_C - ], - 'T_MEMBER_FLAGS': [ - this.tok.T_PUBLIC, - this.tok.T_PRIVATE, - this.tok.T_PROTECTED, - this.tok.T_STATIC, - this.tok.T_ABSTRACT, - this.tok.T_FINAL - ], - 'EOS': [ - ';', - this.tok.T_CLOSE_TAG, - this.EOF, - this.tok.T_INLINE_HTML - ], - 'EXPR': [ - '@','-','+','!','~','(','`', - this.tok.T_LIST, - this.tok.T_CLONE, - this.tok.T_INC, - this.tok.T_DEC, - this.tok.T_NEW, - this.tok.T_ISSET, - this.tok.T_EMPTY, - this.tok.T_INCLUDE, - this.tok.T_INCLUDE_ONCE, - this.tok.T_REQUIRE, - this.tok.T_REQUIRE_ONCE, - this.tok.T_EVAL, - this.tok.T_INT_CAST, - this.tok.T_DOUBLE_CAST, - this.tok.T_STRING_CAST, - this.tok.T_ARRAY_CAST, - this.tok.T_OBJECT_CAST, - this.tok.T_BOOL_CAST, - this.tok.T_UNSET_CAST, - this.tok.T_EXIT, - this.tok.T_PRINT, - this.tok.T_YIELD, - this.tok.T_STATIC, - this.tok.T_FUNCTION, - // using VARIABLES : - this.tok.T_VARIABLE, - '$', - this.tok.T_NS_SEPARATOR, - this.tok.T_STRING, - // using SCALAR : - this.tok.T_STRING, // @see variable.js line 45 > conflict with variable = shift/reduce :) - this.tok.T_CONSTANT_ENCAPSED_STRING, - this.tok.T_START_HEREDOC, - this.tok.T_LNUMBER, - this.tok.T_DNUMBER, - this.tok.T_ARRAY,'[', - this.tok.T_CLASS_C, - this.tok.T_TRAIT_C, - this.tok.T_FUNC_C, - this.tok.T_METHOD_C, - this.tok.T_LINE, - this.tok.T_FILE, - this.tok.T_DIR, - this.tok.T_NS_C - ] + this.tok.T_NS_C, + '"', + 'b"', + 'B"', + "-", + this.tok.T_NS_SEPARATOR, + ].map(mapIt), + ), }; }; /** * helper : gets a token name + * @function Parser#getTokenName + * @memberOf module:php-parser */ -parser.prototype.getTokenName = function(token) { +Parser.prototype.getTokenName = function (token) { if (!isNumber(token)) { return "'" + token + "'"; } else { - if (token == this.EOF) return 'the end of file (EOF)'; + if (token == this.EOF) return "the end of file (EOF)"; return this.lexer.engine.tokens.values[token]; } }; /** * main entry point : converts a source code to AST + * @function Parser#parse + * @memberOf module:php-parser */ -parser.prototype.parse = function(code, filename) { +Parser.prototype.parse = function (code, filename) { this._errors = []; - this.filename = filename || 'eval'; - this.currentNamespace = ['']; + this.filename = filename || "eval"; + this.currentNamespace = [""]; + if (this.extractDoc) { + this._docs = []; + } else { + this._docs = null; + } + if (this.extractTokens) { + this._tokens = []; + } else { + this._tokens = null; + } + this._docIndex = 0; + this._lastNode = null; this.lexer.setInput(code); + this.lexer.all_tokens = this.extractTokens; this.lexer.comment_tokens = this.extractDoc; this.length = this.lexer._input.length; this.innerList = false; - var program = this.ast.prepare('program', this); - var childs = []; - this.nextWithComments(); - while(this.token != this.EOF) { - var node = this.read_start(); - if (node !== null && node !== undefined) { - if (Array.isArray(node)) { - childs = childs.concat(node); - } else { - childs.push(node); - } + this.innerListForm = false; + const program = this.node("program"); + const childs = []; + this.next(); + while (this.token != this.EOF) { + childs.push(this.read_start()); + } + // append last comment + if ( + childs.length === 0 && + this.extractDoc && + this._docs.length > this._docIndex + ) { + childs.push(this.node("noop")()); + } + // #176 : register latest position + this.prev = [ + this.lexer.yylloc.last_line, + this.lexer.yylloc.last_column, + this.lexer.offset, + ]; + const result = program(childs, this._errors, this._docs, this._tokens); + if (this.debug) { + const errors = this.ast.checkNodes(); + /* istanbul ignore next */ + if (errors.length > 0) { + errors.forEach(function (error) { + if (error.position) { + // eslint-disable-next-line no-console + console.log( + "Node at line " + + error.position.line + + ", column " + + error.position.column, + ); + } + // eslint-disable-next-line no-console + console.log(error.stack.join("\n")); + }); + throw new Error("Some nodes are not closed"); } } - return program(childs, this._errors); + return result; }; /** * Raise an error + * @function Parser#raiseError + * @memberOf module:php-parser */ -parser.prototype.raiseError = function(message, msgExpect, expect, token) { - message += ' on line ' + this.lexer.yylloc.first_line; +Parser.prototype.raiseError = function (message, msgExpect, expect, token) { + message += " on line " + this.lexer.yylloc.first_line; if (!this.suppressErrors) { - var err = new SyntaxError( - message, this.filename, this.lexer.yylloc.first_line + const err = new SyntaxError( + message, + this.filename, + this.lexer.yylloc.first_line, ); err.lineNumber = this.lexer.yylloc.first_line; err.fileName = this.filename; - err.columnNumber = this.lexer.yylloc.first_column + err.columnNumber = this.lexer.yylloc.first_column; throw err; } // Error node : - var node = this.ast.prepare('error', this)( - message, token, this.lexer.yylloc.first_line, expect + const node = this.ast.prepare("error", null, this)( + message, + token, + this.lexer.yylloc.first_line, + expect, ); this._errors.push(node); return node; @@ -198,89 +369,185 @@ parser.prototype.raiseError = function(message, msgExpect, expect, token) { /** * handling errors + * @function Parser#error + * @memberOf module:php-parser */ -parser.prototype.error = function(expect) { - var msg = 'Parse Error : syntax error'; - token = this.getTokenName(this.token); +Parser.prototype.error = function (expect) { + let msg = "Parse Error : syntax error"; + let token = this.getTokenName(this.token); + let msgExpect = ""; + if (this.token !== this.EOF) { if (isNumber(this.token)) { - var symbol = this.text(); + let symbol = this.text(); + /* istanbul ignore next */ if (symbol.length > 10) { - symbol = symbol.substring(0, 7) + '...'; + symbol = symbol.substring(0, 7) + "..."; } - token = '\''+symbol+'\' ('+token+')'; + token = "'" + symbol + "' (" + token + ")"; } - msg += ', unexpected ' + token; + msg += ", unexpected " + token; } - var msgExpect = ''; if (expect && !Array.isArray(expect)) { if (isNumber(expect) || expect.length === 1) { - msgExpect = ', expecting ' + this.getTokenName(expect); + msgExpect = ", expecting " + this.getTokenName(expect); } msg += msgExpect; } - this.token !== this.EOF - return this.raiseError( - msg, - msgExpect, - expect, - token + return this.raiseError(msg, msgExpect, expect, token); +}; + +/** + * Create a position node from the lexers position + * + * @function Parser#position + * @memberOf module:php-parser + * @return {Position} + */ +Parser.prototype.position = function () { + return new Position( + this.lexer.yylloc.first_line, + this.lexer.yylloc.first_column, + this.lexer.yylloc.first_offset, ); }; /** * Creates a new AST node + * @function Parser#node + * @memberOf module:php-parser */ -parser.prototype.node = function(name) { - return this.ast.prepare(name, this); +Parser.prototype.node = function (name) { + if (this.extractDoc) { + let docs = null; + if (this._docIndex < this._docs.length) { + docs = this._docs.slice(this._docIndex); + this._docIndex = this._docs.length; + /* istanbul ignore next */ + if (this.debug) { + // eslint-disable-next-line no-console + console.log(new Error("Append docs on " + name)); + // eslint-disable-next-line no-console + console.log(docs); + } + } + const node = this.ast.prepare(name, docs, this); + /* + * TOKENS : + * node1 commentA token commmentB node2 commentC token commentD node3 commentE token + * + * AST : + * structure:S1 [ + * left: node1 ( trail: commentA ), + * right: structure:S2 [ + * node2 (lead: commentB, trail: commentC), + * node3 (lead: commentD) + * ], + * trail: commentE + * ] + * + * Algorithm : + * + * Attach the last comments on parent of current node + * If a new node is started and the parent has a trailing comment + * the move it on previous node + * + * start S2 + * start node1 + * consume node1 & set commentA as trailingComment on S2 + * start S2 + * S1 has a trailingComment, attach it on node1 + * ... + * NOTE : As the trailingComment Behavior depends on AST, it will be build on + * the AST layer - last child node will keep it's trailingComment nodes + */ + node.postBuild = function (self) { + if (this._docIndex < this._docs.length) { + if (this._lastNode) { + const offset = this.prev[2]; + let max = this._docIndex; + for (; max < this._docs.length; max++) { + if (this._docs[max].offset > offset) { + break; + } + } + if (max > this._docIndex) { + // inject trailing comment on child node + this._lastNode.setTrailingComments( + this._docs.slice(this._docIndex, max), + ); + this._docIndex = max; + } + } else if (this.token === this.EOF) { + // end of content + self.setTrailingComments(this._docs.slice(this._docIndex)); + this._docIndex = this._docs.length; + } + } + this._lastNode = self; + }.bind(this); + return node; + } + return this.ast.prepare(name, null, this); }; /** * expects an end of statement or end of file + * @function Parser#expectEndOfStatement + * @memberOf module:php-parser * @return {boolean} */ -parser.prototype.expectEndOfStatement = function() { - if (this.token === ';') { - this.nextWithComments(); - if (this.token === this.tok.T_CLOSE_TAG) { - // strip close tag (statement already closed with ';') - this.nextWithComments(); +Parser.prototype.expectEndOfStatement = function (node) { + if (this.token === ";") { + // include only real ';' statements + // https://github.com/glayzzle/php-parser/issues/164 + if (node && this.lexer.yytext === ";") { + node.includeToken(this); } - } else if (this.token === this.tok.T_CLOSE_TAG) { - this.nextWithComments(); } else if (this.token !== this.tok.T_INLINE_HTML && this.token !== this.EOF) { - this.error(';'); + this.error(";"); return false; } + this.next(); return true; }; -/** outputs some debug information on current token **/ -var ignoreStack = ['parser.next', 'parser.ignoreComments', 'parser.nextWithComments']; -parser.prototype.showlog = function() { - var stack = (new Error()).stack.split('\n'); - var line; - for (var offset = 2; offset < stack.length; offset ++) { +const ignoreStack = ["parser.next", "parser.node", "parser.showlog"]; +/** + * outputs some debug information on current token + * @private + * @function Parser#showlog + * @memberOf module:php-parser + */ +Parser.prototype.showlog = function () { + const stack = new Error().stack.split("\n"); + let line; + for (let offset = 2; offset < stack.length; offset++) { line = stack[offset].trim(); - var found = false; - for(var i = 0; i < ignoreStack.length; i++) { + let found = false; + for (let i = 0; i < ignoreStack.length; i++) { + /* istanbul ignore next */ if (line.substring(3, 3 + ignoreStack[i].length) === ignoreStack[i]) { found = true; break; } } + /* istanbul ignore next */ if (!found) { break; } } - + // eslint-disable-next-line no-console console.log( - 'Line ' - + this.lexer.yylloc.first_line - + ' : ' - + this.getTokenName(this.token) - + ">" + this.lexer.yytext + "<" - + ' @-->' + line + "Line " + + this.lexer.yylloc.first_line + + " : " + + this.getTokenName(this.token) + + ">" + + this.lexer.yytext + + "<" + + " @-->" + + line, ); return this; }; @@ -294,11 +561,13 @@ parser.prototype.showlog = function() { * If the suppressError mode is activated, then the error will * be added to the program error stack and this function will return `false`. * + * @function Parser#expect + * @memberOf module:php-parser * @param {String|Number} token * @return {boolean} * @throws Error */ -parser.prototype.expect = function(token) { +Parser.prototype.expect = function (token) { if (Array.isArray(token)) { if (token.indexOf(this.token) === -1) { this.error(token); @@ -313,79 +582,167 @@ parser.prototype.expect = function(token) { /** * Returns the current token contents + * @function Parser#text + * @memberOf module:php-parser * @return {String} */ -parser.prototype.text = function() { +Parser.prototype.text = function () { return this.lexer.yytext; }; -/** consume the next token **/ -parser.prototype.next = function() { +/** + * consume the next token + * @function Parser#next + * @memberOf module:php-parser + */ +Parser.prototype.next = function () { + // prepare the back command + if (this.token !== ";" || this.lexer.yytext === ";") { + // ignore '?>' from automated resolution + // https://github.com/glayzzle/php-parser/issues/168 + this.prev = [ + this.lexer.yylloc.last_line, + this.lexer.yylloc.last_column, + this.lexer.offset, + ]; + } + + // eating the token + this.lex(); + + // showing the debug if (this.debug) { this.showlog(); - this.debug = false; - this.nextWithComments().ignoreComments(); - this.debug = true; - } else { - this.nextWithComments().ignoreComments(); } - return this; -}; -/** consume comments (if found) **/ -parser.prototype.ignoreComments = function() { - if (this.debug) this.showlog(); - while(this.token === this.tok.T_COMMENT || this.token === this.tok.T_DOC_COMMENT) { - // IGNORE COMMENTS - this.nextWithComments(); + // handling comments + if (this.extractDoc) { + while ( + this.token === this.tok.T_COMMENT || + this.token === this.tok.T_DOC_COMMENT + ) { + // APPEND COMMENTS + if (this.token === this.tok.T_COMMENT) { + this._docs.push(this.read_comment()); + } else { + this._docs.push(this.read_doc_comment()); + } + } } + return this; }; -/** consume the next token (including doc) **/ -parser.prototype.nextWithComments = function() { - this.prev = [ - this.lexer.yylloc.first_line, - this.lexer.yylloc.first_column, - this.lexer.offset - ]; - this.token = this.lexer.lex() || this.EOF; - if (this.debug) this.showlog(); +/** + * Peek at the next token. + * @function Parser#peek + * @memberOf module:php-parser + * @returns {string|number} Next Token + */ +Parser.prototype.peek = function () { + const lexerState = this.lexer.getState(); + const nextToken = this.lexer.lex(); + this.lexer.setState(lexerState); + return nextToken; +}; + +/** + * Eating a token + * @function Parser#lex + * @memberOf module:php-parser + */ +Parser.prototype.lex = function () { + // append on token stack + if (this.extractTokens) { + do { + // the token + this.token = this.lexer.lex() || /* istanbul ignore next */ this.EOF; + if (this.token === this.EOF) return this; + let entry = this.lexer.yytext; + if ( + Object.prototype.hasOwnProperty.call( + this.lexer.engine.tokens.values, + this.token, + ) + ) { + entry = [ + this.lexer.engine.tokens.values[this.token], + entry, + this.lexer.yylloc.first_line, + this.lexer.yylloc.first_offset, + this.lexer.offset, + ]; + } else { + entry = [ + null, + entry, + this.lexer.yylloc.first_line, + this.lexer.yylloc.first_offset, + this.lexer.offset, + ]; + } + this._tokens.push(entry); + if (this.token === this.tok.T_CLOSE_TAG) { + // https://github.com/php/php-src/blob/7ff186434e82ee7be7c59d0db9a976641cf7b09c/Zend/zend_compile.c#L1680 + this.token = ";"; + return this; + } else if (this.token === this.tok.T_OPEN_TAG_WITH_ECHO) { + this.token = this.tok.T_ECHO; + return this; + } + } while ( + this.token === this.tok.T_WHITESPACE || // ignore white space + (!this.extractDoc && + (this.token === this.tok.T_COMMENT || // ignore single lines comments + this.token === this.tok.T_DOC_COMMENT)) || // ignore doc comments + // ignore open tags + this.token === this.tok.T_OPEN_TAG + ); + } else { + this.token = this.lexer.lex() || /* istanbul ignore next */ this.EOF; + } return this; }; /** * Check if token is of specified type + * @function Parser#is + * @memberOf module:php-parser */ -parser.prototype.is = function(type) { +Parser.prototype.is = function (type) { if (Array.isArray(type)) { return type.indexOf(this.token) !== -1; - } else { - return this.entries[type].indexOf(this.token) != -1; } + return this.entries[type].has(this.token); }; // extends the parser with syntax files [ - require('./parser/array.js'), - require('./parser/class.js'), - require('./parser/comment.js'), - require('./parser/expr.js'), - require('./parser/function.js'), - require('./parser/if.js'), - require('./parser/loops.js'), - require('./parser/main.js'), - require('./parser/namespace.js'), - require('./parser/scalar.js'), - require('./parser/statement.js'), - require('./parser/switch.js'), - require('./parser/try.js'), - require('./parser/utils.js'), - require('./parser/variable.js') + require("./parser/array.js"), + require("./parser/class.js"), + require("./parser/comment.js"), + require("./parser/expr.js"), + require("./parser/enum.js"), + require("./parser/function.js"), + require("./parser/if.js"), + require("./parser/loops.js"), + require("./parser/main.js"), + require("./parser/namespace.js"), + require("./parser/scalar.js"), + require("./parser/statement.js"), + require("./parser/switch.js"), + require("./parser/try.js"), + require("./parser/utils.js"), + require("./parser/variable.js"), ].forEach(function (ext) { - for(var k in ext) { - parser.prototype[k] = ext[k]; + for (const k in ext) { + /* istanbul ignore next */ + if (Object.prototype.hasOwnProperty.call(Parser.prototype, k)) { + // @see https://github.com/glayzzle/php-parser/issues/234 + throw new Error("Function " + k + " is already defined - collision"); + } + Parser.prototype[k] = ext[k]; } }); -module.exports = parser; +module.exports = Parser; diff --git a/src/parser/array.js b/src/parser/array.js index f1bbd4344..0d354b209 100644 --- a/src/parser/array.js +++ b/src/parser/array.js @@ -1,73 +1,105 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ -var ArrayExpr = 'array'; -var ArrayEntry = 'entry'; +"use strict"; module.exports = { - /** + /* * Parse an array * ```ebnf * array ::= T_ARRAY '(' array_pair_list ')' | * '[' array_pair_list ']' * ``` */ - read_array: function() { - var expect = null; - var shortForm = false; - var items = []; - var result = this.node(ArrayExpr); + read_array: function () { + let expect = null; + let shortForm = false; + const result = this.node("array"); if (this.token === this.tok.T_ARRAY) { - this.next().expect('('); - expect = ')'; + this.next().expect("("); + expect = ")"; } else { shortForm = true; - expect = ']'; + expect = "]"; } - - if (this.next().token != expect) { - while(this.token != this.EOF) { - items.push(this.read_array_pair_list()); - if (this.token == ',') { - this.next(); - if (this.token === expect) { - break; - } - } else break; - } + let items = []; + if (this.next().token !== expect) { + items = this.read_array_pair_list(shortForm); } this.expect(expect); this.next(); return result(shortForm, items); }, - /** - * Reads an array entry item + /* + * Reads an array of items * ```ebnf - * array_pair_list ::= '&' w_variable | - * ( - * expr ( - * T_DOUBLE_ARROW ( - * expr | '&' w_variable - * ) - * )? - * ) + * array_pair_list ::= array_pair (',' array_pair?)* * ``` */ - read_array_pair_list: function() { - var result = this.node(ArrayEntry); - var key = null; - var value = null; - if (this.token === '&') { - value = this.next().read_variable(true, false, true); + read_array_pair_list: function (shortForm) { + const self = this; + return this.read_list( + function () { + return self.read_array_pair(shortForm); + }, + ",", + true, + ); + }, + /* + * Reads an entry + * array_pair: + * expr T_DOUBLE_ARROW expr + * | expr + * | expr T_DOUBLE_ARROW '&' variable + * | '&' variable + * | expr T_DOUBLE_ARROW T_LIST '(' array_pair_list ')' + * | T_LIST '(' array_pair_list ')' + */ + read_array_pair: function (shortForm) { + if ( + (!shortForm && this.token === ")") || + (shortForm && this.token === "]") + ) { + return; + } + + if (this.token === ",") { + return this.node("noop")(); + } + + const entry = this.node("entry"); + + let key = null; + let value = null; + let byRef = false; + let unpack = false; + + if (this.token === "&") { + this.next(); + byRef = true; + value = this.read_variable(true, false); + } else if (this.token === this.tok.T_ELLIPSIS && this.version >= 704) { + this.next(); + if (this.token === "&") { + this.error(); + } + unpack = true; + value = this.read_expr(); } else { - var expr = this.read_expr(); + const expr = this.read_expr(); + if (this.token === this.tok.T_DOUBLE_ARROW) { + this.next(); key = expr; - if (this.next().token === '&') { - value = this.next().read_variable(true, false, true); + + if (this.token === "&") { + this.next(); + byRef = true; + value = this.read_variable(true, false); } else { value = this.read_expr(); } @@ -75,15 +107,7 @@ module.exports = { value = expr; } } - return result(key, value); + + return entry(key, value, byRef, unpack); }, - /** - * ```ebnf - * dim_offset ::= expr? - * ``` - */ - read_dim_offset: function() { - if (this.token == ']') return false; - return this.read_expr(); - } }; diff --git a/src/parser/class.js b/src/parser/class.js index a294d65c4..cbc2c370f 100644 --- a/src/parser/class.js +++ b/src/parser/class.js @@ -1,69 +1,82 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; module.exports = { - /** + /* * reading a class * ```ebnf * class ::= class_scope? T_CLASS T_STRING (T_EXTENDS NAMESPACE_NAME)? (T_IMPLEMENTS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' CLASS_BODY '}' * ``` */ - read_class: function(flag) { - var result = this.node('class'); - this.expect(this.tok.T_CLASS); - this.next().expect(this.tok.T_STRING); - var propName = this.text() - , propExtends = null - , propImplements = null - , body - ; - if (this.next().token == this.tok.T_EXTENDS) { - propExtends = this.next().read_namespace_name(); - } - if (this.token == this.tok.T_IMPLEMENTS) { - propImplements = this.next().read_name_list(); + read_class_declaration_statement: function (attrs) { + const result = this.node("class"); + const flag = this.read_class_modifiers(); + // graceful mode : ignore token & go next + if (this.token !== this.tok.T_CLASS) { + this.error(this.tok.T_CLASS); + this.next(); + return null; } - this.expect('{'); - body = this.nextWithComments().read_class_body(); - return result( - propName - ,propExtends - ,propImplements - ,body - ,flag - ); - } - /** - * Read the class visibility - * ```ebnf - * class_scope ::= (T_FINAL | T_ABSTRACT)? - * ``` - */ - ,read_class_scope: function() { - var result = this.token; - if (result == this.tok.T_FINAL) { + this.next().expect(this.tok.T_STRING); + let propName = this.node("identifier"); + const name = this.text(); + this.next(); + propName = propName(name); + const propExtends = this.read_extends_from(); + const propImplements = this.read_implements_list(); + this.expect("{"); + const body = this.next().read_class_body(true, false); + const node = result(propName, propExtends, propImplements, body, flag); + if (attrs) node.attrGroups = attrs; + return node; + }, + + read_class_modifiers: function () { + const modifier = this.read_class_modifier({ + readonly: 0, + final_or_abstract: 0, + }); + return [0, 0, modifier.final_or_abstract, modifier.readonly]; + }, + + read_class_modifier: function (memo) { + if (this.token === this.tok.T_READ_ONLY) { this.next(); - return [0, 0, 2]; - } else if (result == this.tok.T_ABSTRACT) { + memo.readonly = 1; + memo = this.read_class_modifier(memo); + } else if ( + memo.final_or_abstract === 0 && + this.token === this.tok.T_ABSTRACT + ) { this.next(); - return [0, 0, 1]; + memo.final_or_abstract = 1; + memo = this.read_class_modifier(memo); + } else if ( + memo.final_or_abstract === 0 && + this.token === this.tok.T_FINAL + ) { + this.next(); + memo.final_or_abstract = 2; + memo = this.read_class_modifier(memo); } - return [0, 0, 0]; - } - /** + + return memo; + }, + + /* * Reads a class body * ```ebnf * class_body ::= (member_flags? (T_VAR | T_STRING | T_FUNCTION))* * ``` */ - ,read_class_body: function() { - var result = []; - - while(this.token !== this.EOF && this.token !== '}') { - + read_class_body: function (allow_variables, allow_enum_cases) { + let result = []; + let attrs = []; + while (this.token !== this.EOF && this.token !== "}") { if (this.token === this.tok.T_COMMENT) { result.push(this.read_comment()); continue; @@ -76,69 +89,99 @@ module.exports = { // check T_USE trait if (this.token === this.tok.T_USE) { - result = result.concat( - this.next().read_trait_use_statement() - ); + result = result.concat(this.read_trait_use_statement()); + continue; + } + + // check enum cases + if (allow_enum_cases && this.token === this.tok.T_CASE) { + const enumcase = this.read_enum_case(); + if (this.expect(";")) { + this.next(); + } + result = result.concat(enumcase); continue; } + if (this.token === this.tok.T_ATTRIBUTE) { + attrs = this.read_attr_list(); + } + + const locStart = this.position(); + // read member flags - var flags = this.read_member_flags(false); + const flags = this.read_member_flags(false); // check constant if (this.token === this.tok.T_CONST) { - var constants = this.read_constant_list(flags); - this.expect(';'); - this.nextWithComments(); + const constants = this.read_constant_list(flags, attrs); + if (this.expect(";")) { + this.next(); + } result = result.concat(constants); continue; } // jump over T_VAR then land on T_VARIABLE - if (this.token === this.tok.T_VAR) { + if (allow_variables && this.token === this.tok.T_VAR) { this.next().expect(this.tok.T_VARIABLE); - flags[0] = flags[1] = 0; // public & non static var + flags[0] = null; // public (as null) + flags[1] = 0; // non static var } - if (this.token === this.tok.T_VARIABLE) { - + if (this.token === this.tok.T_FUNCTION) { + // reads a function + result.push(this.read_function(false, flags, attrs, locStart)); + attrs = []; + } else if ( + allow_variables && + (this.token === this.tok.T_VARIABLE || + (this.version >= 801 && this.token === this.tok.T_READ_ONLY) || + // support https://wiki.php.net/rfc/typed_properties_v2 + (this.version >= 704 && + (this.token === "?" || + this.token === this.tok.T_ARRAY || + this.token === this.tok.T_CALLABLE || + this.token === this.tok.T_NAMESPACE || + this.token === this.tok.T_NAME_FULLY_QUALIFIED || + this.token === this.tok.T_NAME_QUALIFIED || + this.token === this.tok.T_NAME_RELATIVE || + this.token === this.tok.T_NS_SEPARATOR || + this.token === this.tok.T_STRING))) + ) { // reads a variable - var variables = this.read_variable_list(flags); - this.expect(';'); - this.nextWithComments(); + const variables = this.read_variable_list(flags, attrs); + attrs = []; + this.expect(";"); + this.next(); result = result.concat(variables); - - } else if (this.token === this.tok.T_FUNCTION) { - - // reads a function - result.push(this.read_function(false, flags)); - } else { - // raise an error this.error([ this.tok.T_CONST, - this.tok.T_VARIABLE, - this.tok.T_FUNCTION + ...(allow_variables ? [this.tok.T_VARIABLE] : []), + ...(allow_enum_cases ? [this.tok.T_CASE] : []), + this.tok.T_FUNCTION, ]); // ignore token this.next(); - } } - this.expect('}'); - this.nextWithComments(); + this.expect("}"); + this.next(); return result; - } - /** + }, + /* * Reads variable list * ```ebnf * variable_list ::= (variable_declaration ',')* variable_declaration * ``` */ - ,read_variable_list: function(flags) { - return this.read_list( - /** + read_variable_list: function (flags, attrs) { + const result = this.node("propertystatement"); + + const properties = this.read_list( + /* * Reads a variable declaration * * ```ebnf @@ -146,81 +189,127 @@ module.exports = { * ``` */ function read_variable_declaration() { - var result = this.node('property'); + const result = this.node("property"); + let readonly = false; + if (this.token === this.tok.T_READ_ONLY) { + readonly = true; + this.next(); + } + const [nullable, type] = this.read_optional_type(); this.expect(this.tok.T_VARIABLE); - var name = this.text().substring(1); // ignore $ + let propName = this.node("identifier"); + const name = this.text().substring(1); // ignore $ this.next(); - if (this.token === ';' || this.token === ',') { - return result(name, null, flags); - } else if(this.token === '=') { + propName = propName(name); + + let value = null; + + this.expect([",", ";", "="]); + if (this.token === "=") { // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L815 - return result(name, this.next().read_expr(), flags); - } else { - this.expect([',', ';', '=']); - return result(name, null, flags); + value = this.next().read_expr(); } - }, ',' + return result(propName, value, readonly, nullable, type, attrs || []); + }, + ",", ); - } - /** + + return result(null, properties, flags); + }, + /* * Reads constant list * ```ebnf - * constant_list ::= T_CONST (constant_declaration ',')* constant_declaration + * constant_list ::= T_CONST [type] (constant_declaration ',')* constant_declaration * ``` */ - ,read_constant_list: function(flags) { + read_constant_list: function (flags, attrs) { if (this.expect(this.tok.T_CONST)) { this.next(); } - return this.read_list( - /** - * Reads a constant declaration - * - * ```ebnf - * constant_declaration ::= T_STRING '=' expr - * ``` - * @return {Constant} [:link:](AST.md#constant) - */ - function read_constant_declaration() { - var result = this.node('classconstant'), name = null, value = null; - if (this.expect(this.tok.T_STRING)) { - name = this.text(); - this.next(); - } - if (this.expect('=')) { - value = this.next().read_expr(); - } - return result(name, value, flags); - }, ',' - ) - ; - } - /** + + const [nullable, type] = + this.version >= 803 ? this.read_optional_type() : [false, null]; + + const result = this.node("classconstant"); + const items = this.read_list( + /* + * Reads a constant declaration + * + * ```ebnf + * constant_declaration ::= (T_STRING | IDENTIFIER) '=' expr + * ``` + * @return {Constant} [:link:](AST.md#constant) + */ + function read_constant_declaration() { + const result = this.node("constant"); + let constName = null; + let value = null; + if ( + this.token === this.tok.T_STRING || + (this.version >= 700 && this.is("IDENTIFIER")) + ) { + constName = this.node("identifier"); + const name = this.text(); + this.next(); + constName = constName(name); + } else { + this.expect("IDENTIFIER"); + } + if (this.expect("=")) { + value = this.next().read_expr(); + } + return result(constName, value); + }, + ",", + ); + + return result(null, items, flags, nullable, type, attrs || []); + }, + /* * Read member flags * @return array * 1st index : 0 => public, 1 => protected, 2 => private * 2nd index : 0 => instance member, 1 => static member * 3rd index : 0 => normal, 1 => abstract member, 2 => final member */ - ,read_member_flags: function(asInterface) { - var result = [-1, -1, -1]; - if (this.is('T_MEMBER_FLAGS')) { - var idx = 0, val = 0; + read_member_flags: function (asInterface) { + const result = [-1, -1, -1]; + if (this.is("T_MEMBER_FLAGS")) { + let idx = 0, + val = 0; do { - switch(this.token) { - case this.tok.T_PUBLIC: idx = 0; val = 0; break; - case this.tok.T_PROTECTED: idx = 0; val = 1; break; - case this.tok.T_PRIVATE: idx = 0; val = 2; break; - case this.tok.T_STATIC: idx = 1; val = 1; break; - case this.tok.T_ABSTRACT: idx = 2; val = 1; break; - case this.tok.T_FINAL: idx = 2; val = 2; break; + switch (this.token) { + case this.tok.T_PUBLIC: + idx = 0; + val = 0; + break; + case this.tok.T_PROTECTED: + idx = 0; + val = 1; + break; + case this.tok.T_PRIVATE: + idx = 0; + val = 2; + break; + case this.tok.T_STATIC: + idx = 1; + val = 1; + break; + case this.tok.T_ABSTRACT: + idx = 2; + val = 1; + break; + case this.tok.T_FINAL: + idx = 2; + val = 2; + break; } if (asInterface) { - if (idx == 0 && val == 2) { + if (idx === 0 && val === 2) { // an interface can't be private this.expect([this.tok.T_PUBLIC, this.tok.T_PROTECTED]); val = -1; - } else if (idx == 2 && val == 1) { + } else if (idx === 2 && val === 1) { // an interface cant be abstract this.error(); val = -1; @@ -232,48 +321,105 @@ module.exports = { } else if (val !== -1) { result[idx] = val; } - } while(this.next().is('T_MEMBER_FLAGS')); + } while (this.next().is("T_MEMBER_FLAGS")); } - if (result[0] == -1) result[0] = 0; - if (result[1] == -1) result[1] = 0; - if (result[2] == -1) result[2] = 0; + if (result[1] === -1) result[1] = 0; + if (result[2] === -1) result[2] = 0; return result; - } - /** + }, + + /* + * optional_type: + * /- empty -/ { $$ = NULL; } + * | type_expr { $$ = $1; } + * ; + * + * type_expr: + * type { $$ = $1; } + * | '?' type { $$ = $2; $$->attr |= ZEND_TYPE_NULLABLE; } + * | union_type { $$ = $1; } + * ; + * + * type: + * T_ARRAY { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_ARRAY); } + * | T_CALLABLE { $$ = zend_ast_create_ex(ZEND_AST_TYPE, IS_CALLABLE); } + * | name { $$ = $1; } + * ; + * + * union_type: + * type '|' type { $$ = zend_ast_create_list(2, ZEND_AST_TYPE_UNION, $1, $3); } + * | union_type '|' type { $$ = zend_ast_list_add($1, $3); } + * ; + */ + read_optional_type: function () { + const nullable = this.token === "?"; + if (nullable) { + this.next(); + } + + if (this.peek() === "=") { + return [false, null]; + } + + let type = this.read_types(); + if (nullable && !type) { + this.raiseError( + "Expecting a type definition combined with nullable operator", + ); + } + if (!nullable && !type) { + return [false, null]; + } + if (this.token === "|") { + type = [type]; + do { + this.next(); + const variant = this.read_type(); + if (!variant) { + this.raiseError("Expecting a type definition"); + break; + } + type.push(variant); + } while (this.token === "|"); + } + return [nullable, type]; + }, + + /* * reading an interface * ```ebnf * interface ::= T_INTERFACE T_STRING (T_EXTENDS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' INTERFACE_BODY '}' * ``` */ - ,read_interface: function() { - var result = this.node('interface'), name = null, body = null, propExtends = null; - if (this.expect(this.tok.T_INTERFACE)) { + read_interface_declaration_statement: function (attrs) { + const result = this.node("interface"); + if (this.token !== this.tok.T_INTERFACE) { + this.error(this.tok.T_INTERFACE); this.next(); + return null; } - if (this.expect(this.tok.T_STRING)) { - name = this.text(); - this.next(); - } - if (this.token === this.tok.T_EXTENDS) { - propExtends = this.next().read_name_list(); - } - if (this.expect('{')) { - body = this.next().read_interface_body(); - } - return result(name, propExtends, body); - } - /** + this.next().expect(this.tok.T_STRING); + let propName = this.node("identifier"); + const name = this.text(); + this.next(); + propName = propName(name); + const propExtends = this.read_interface_extends_list(); + this.expect("{"); + const body = this.next().read_interface_body(); + return result(propName, propExtends, body, attrs || []); + }, + /* * Reads an interface body * ```ebnf * interface_body ::= (member_flags? (T_CONST | T_FUNCTION))* * ``` */ - ,read_interface_body: function() { - var result = []; - - while(this.token !== this.EOF && this.token !== '}') { + read_interface_body: function () { + let result = [], + attrs = []; + while (this.token !== this.EOF && this.token !== "}") { if (this.token === this.tok.T_COMMENT) { result.push(this.read_comment()); continue; @@ -284,160 +430,176 @@ module.exports = { continue; } + const locStart = this.position(); + + attrs = this.read_attr_list(); // read member flags - var flags = this.read_member_flags(true); + const flags = this.read_member_flags(true); // check constant - if (this.token == this.tok.T_CONST) { - var constants = this.read_constant_list(flags); - if (this.expect(';')) { - this.nextWithComments(); + if (this.token === this.tok.T_CONST) { + const constants = this.read_constant_list(flags, attrs); + if (this.expect(";")) { + this.next(); } result = result.concat(constants); - } - - // reads a function - else if (this.token === this.tok.T_FUNCTION) { - var method = this.read_function_declaration(2, flags); + attrs = []; + } else if (this.token === this.tok.T_FUNCTION) { + // reads a function + const method = this.read_function_declaration( + 2, + flags, + attrs, + locStart, + ); method.parseFlags(flags); result.push(method); - if (this.expect(';')) { - this.nextWithComments(); + if (this.expect(";")) { + this.next(); } + attrs = []; } else { // raise an error - this.error([ - this.tok.T_CONST, - this.tok.T_FUNCTION - ]); + this.error([this.tok.T_CONST, this.tok.T_FUNCTION]); this.next(); } } - if (this.expect('}')) { + if (this.expect("}")) { this.next(); } return result; - } - /** + }, + /* * reading a trait * ```ebnf * trait ::= T_TRAIT T_STRING (T_EXTENDS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' FUNCTION* '}' * ``` */ - ,read_trait: function(flag) { - var result = this.node('trait'), - propName = null, - propExtends = null, - propImplements = null, - body = null; - if (this.expect(this.tok.T_TRAIT)) { + read_trait_declaration_statement: function () { + const result = this.node("trait"); + // graceful mode : ignore token & go next + if (this.token !== this.tok.T_TRAIT) { + this.error(this.tok.T_TRAIT); this.next(); + return null; } - if (this.expect(this.tok.T_STRING)) { - propName = this.text(); - } - if (this.next().token == this.tok.T_EXTENDS) { - propExtends = this.next().read_namespace_name(); - } - if (this.token == this.tok.T_IMPLEMENTS) { - propImplements = this.next().read_name_list(); - } - if (this.expect('{')) { - body = this.next().read_class_body(); - } - return result( - propName, - propExtends, - propImplements, - body - ); - } - /** + this.next().expect(this.tok.T_STRING); + let propName = this.node("identifier"); + const name = this.text(); + this.next(); + propName = propName(name); + this.expect("{"); + const body = this.next().read_class_body(true, false); + return result(propName, body); + }, + /* * reading a use statement * ```ebnf * trait_use_statement ::= namespace_name (',' namespace_name)* ('{' trait_use_alias '}')? * ``` */ - ,read_trait_use_statement: function() { + read_trait_use_statement: function () { // defines use statements - var node = this.node('traituse'); - var traits = [this.read_namespace_name()]; - var adaptations = null; - while(this.token === ',') { - traits.push( - this.next().read_namespace_name() - ); + const node = this.node("traituse"); + this.expect(this.tok.T_USE) && this.next(); + const traits = [this.read_namespace_name()]; + let adaptations = null; + while (this.token === ",") { + traits.push(this.next().read_namespace_name()); } - if (this.token === '{') { + if (this.token === "{") { adaptations = []; // defines alias statements - while(this.next().token !== this.EOF) { - if (this.token === '}') break; + while (this.next().token !== this.EOF) { + if (this.token === "}") break; adaptations.push(this.read_trait_use_alias()); - this.expect(';'); + this.expect(";"); } - if (this.expect('}')) { - this.nextWithComments(); + if (this.expect("}")) { + this.next(); } } else { - if (this.expect(';')) { - this.nextWithComments(); + if (this.expect(";")) { + this.next(); } } return node(traits, adaptations); - } - /** + }, + /* * Reading trait alias * ```ebnf * trait_use_alias ::= namespace_name ( T_DOUBLE_COLON T_STRING )? (T_INSTEADOF namespace_name) | (T_AS member_flags? T_STRING) * ``` + * name list : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L303 + * trait adaptation : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L742 */ - ,read_trait_use_alias: function() { - var node = this.node(); - var trait = null; - var method = this.read_namespace_name(); - - if (this.token === this.tok.T_DOUBLE_COLON) { - if (this.next().expect(this.tok.T_STRING)) { - trait = method; - method = this.text(); + read_trait_use_alias: function () { + const node = this.node(); + let trait = null; + let method; + + if (this.is("IDENTIFIER")) { + method = this.node("identifier"); + const methodName = this.text(); + this.next(); + method = method(methodName); + } else { + method = this.read_namespace_name(); + + if (this.token === this.tok.T_DOUBLE_COLON) { this.next(); + if ( + this.token === this.tok.T_STRING || + (this.version >= 700 && this.is("IDENTIFIER")) + ) { + trait = method; + method = this.node("identifier"); + const methodName = this.text(); + this.next(); + method = method(methodName); + } else { + this.expect(this.tok.T_STRING); + } + } else { + // convert identifier as string + method = method.name; } - } else { - // convert identifier as string - method = method.name; } // handle trait precedence if (this.token === this.tok.T_INSTEADOF) { return node( - 'traitprecedence', - trait, method, - this.next().read_name_list() + "traitprecedence", + trait, + method, + this.next().read_name_list(), ); - } - - // handle trait alias - else if (this.token === this.tok.T_AS) { - var flags = false; - var alias = null; - if (this.next().is('T_MEMBER_FLAGS')) { + } else if (this.token === this.tok.T_AS) { + // handle trait alias + let flags = null; + let alias = null; + if (this.next().is("T_MEMBER_FLAGS")) { flags = this.read_member_flags(); } - if (this.token === this.tok.T_STRING) { - alias = this.text(); + if ( + this.token === this.tok.T_STRING || + (this.version >= 700 && this.is("IDENTIFIER")) + ) { + alias = this.node("identifier"); + const name = this.text(); this.next(); + alias = alias(name); } else if (flags === false) { // no visibility flags and no name => too bad this.expect(this.tok.T_STRING); } - return node('traitalias', trait, method, alias, flags) + return node("traitalias", trait, method, alias, flags); } // handle errors this.expect([this.tok.T_AS, this.tok.T_INSTEADOF]); - return node('traitalias', trait, method, null, null); - } + return node("traitalias", trait, method, null, null); + }, }; diff --git a/src/parser/comment.js b/src/parser/comment.js index 23ad88752..fdddb2529 100644 --- a/src/parser/comment.js +++ b/src/parser/comment.js @@ -1,45 +1,52 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ - -var docSplit = /^(\s*\*[ \t]*|[ \t]*)(.*)$/gm; +"use strict"; module.exports = { - /** + /* * Comments with // or # or / * ... * / */ - read_comment: function() { - var result = this.node('doc'); - var lines = []; - do { - var line = this.text(); - if (line[0] === '#') { - line = line.substring(1); - } else { - line = line.substring(2); - if (line.substring(line.length - 2) === '*/') { - line = line.substring(0, line.length - 2); - } - } - lines.push(line.trim()); - } while(this.nextWithComments().token === this.tok.T_COMMENT); - return result(false, lines); + read_comment: function () { + const text = this.text(); + let result = this.ast.prepare( + text.substring(0, 2) === "/*" ? "commentblock" : "commentline", + null, + this, + ); + const offset = this.lexer.yylloc.first_offset; + // handle location on comment + const prev = this.prev; + this.prev = [ + this.lexer.yylloc.last_line, + this.lexer.yylloc.last_column, + this.lexer.offset, + ]; + this.lex(); + result = result(text); + result.offset = offset; + this.prev = prev; + return result; }, - /** + /* * Comments with / ** ... * / */ - read_doc_comment: function() { - var result = this.node('doc'); - var text = this.text(); - text = text.substring(2, text.length - 2); - var lines = []; - text = text.split(docSplit); - for(var i = 2; i < text.length; i += 3) { - lines.push(text[i].trim()); - } - this.nextWithComments(); - return result(true, lines); - } + read_doc_comment: function () { + let result = this.ast.prepare("commentblock", null, this); + const offset = this.lexer.yylloc.first_offset; + const text = this.text(); + const prev = this.prev; + this.prev = [ + this.lexer.yylloc.last_line, + this.lexer.yylloc.last_column, + this.lexer.offset, + ]; + this.lex(); + result = result(text); + result.offset = offset; + this.prev = prev; + return result; + }, }; diff --git a/src/parser/enum.js b/src/parser/enum.js new file mode 100644 index 000000000..f380fe390 --- /dev/null +++ b/src/parser/enum.js @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) + * @authors https://github.com/glayzzle/php-parser/graphs/contributors + * @url http://glayzzle.com + */ +"use strict"; + +module.exports = { + /* + * reading an enum + * ```ebnf + * enum ::= enum_scope? T_ENUM T_STRING (':' NAMESPACE_NAME)? (T_IMPLEMENTS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' ENUM_BODY '}' + * ``` + */ + read_enum_declaration_statement: function (attrs) { + const result = this.node("enum"); + // graceful mode : ignore token & go next + if (!this.expect(this.tok.T_ENUM)) { + return null; + } + this.next().expect(this.tok.T_STRING); + let propName = this.node("identifier"); + const name = this.text(); + this.next(); + propName = propName(name); + const valueType = this.read_enum_value_type(); + const propImplements = this.read_implements_list(); + this.expect("{"); + const body = this.next().read_class_body(false, true); + const node = result(propName, valueType, propImplements, body); + if (attrs) node.attrGroups = attrs; + return node; + }, + + read_enum_value_type: function () { + if (this.token === ":") { + return this.next().read_namespace_name(); + } + + return null; + }, + + read_enum_case: function () { + this.expect(this.tok.T_CASE); + const result = this.node("enumcase"); + let caseName = this.node("identifier"); + const name = this.next().text(); + this.next(); + caseName = caseName(name); + + const value = this.token === "=" ? this.next().read_expr() : null; + this.expect(";"); + + return result(caseName, value); + }, +}; diff --git a/src/parser/expr.js b/src/parser/expr.js index 79873a135..538fffdbd 100644 --- a/src/parser/expr.js +++ b/src/parser/expr.js @@ -1,320 +1,425 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; module.exports = { - - read_expr: function() { - var result = this.node(); - var expr = this.read_expr_item(); + read_expr: function (expr) { + const result = this.node(); + if (this.token === "@") { + if (!expr) { + expr = this.next().read_expr(); + } + return result("silent", expr); + } + if (!expr) { + expr = this.read_expr_item(); + } // binary operations - if (this.token === '|') - return result('bin', '|', expr, this.next().read_expr()); - if (this.token === '&') - return result('bin', '&', expr, this.next().read_expr()); - if (this.token === '^') - return result('bin', '^', expr, this.next().read_expr()); - if (this.token === '.') - return result('bin', '.', expr, this.next().read_expr()); - if (this.token === '+') - return result('bin', '+', expr, this.next().read_expr()); - if (this.token === '-') - return result('bin', '-', expr, this.next().read_expr()); - if (this.token === '*') - return result('bin', '*', expr, this.next().read_expr()); - if (this.token === '/') - return result('bin', '/', expr, this.next().read_expr()); - if (this.token === '%') - return result('bin', '%', expr, this.next().read_expr()); - if (this.token === this.tok.T_POW) - return result('bin', '**', expr, this.next().read_expr()); - if (this.token === this.tok.T_SL) - return result('bin', '<<', expr, this.next().read_expr()); - if (this.token === this.tok.T_SR) - return result('bin', '>>', expr, this.next().read_expr()); + if (this.token === "|") { + return result("bin", "|", expr, this.next().read_expr()); + } + if (this.token === "&") { + return result("bin", "&", expr, this.next().read_expr()); + } + if (this.token === "^") { + return result("bin", "^", expr, this.next().read_expr()); + } + if (this.token === ".") { + return result("bin", ".", expr, this.next().read_expr()); + } + if (this.token === "+") { + return result("bin", "+", expr, this.next().read_expr()); + } + if (this.token === "-") { + return result("bin", "-", expr, this.next().read_expr()); + } + if (this.token === "*") { + return result("bin", "*", expr, this.next().read_expr()); + } + if (this.token === "/") { + return result("bin", "/", expr, this.next().read_expr()); + } + if (this.token === "%") { + return result("bin", "%", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_POW) { + return result("bin", "**", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_SL) { + return result("bin", "<<", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_SR) { + return result("bin", ">>", expr, this.next().read_expr()); + } // more binary operations (formerly bool) - if (this.token === this.tok.T_BOOLEAN_OR) - return result('bin', '||', expr, this.next().read_expr()); - if (this.token === this.tok.T_LOGICAL_OR) - return result('bin', 'or', expr, this.next().read_expr()); - if (this.token === this.tok.T_BOOLEAN_AND) - return result('bin', '&&', expr, this.next().read_expr()); - if (this.token === this.tok.T_LOGICAL_AND) - return result('bin', 'and', expr, this.next().read_expr()); - if (this.token === this.tok.T_LOGICAL_XOR) - return result('bin', 'xor', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_IDENTICAL) - return result('bin', '===', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_NOT_IDENTICAL) - return result('bin', '!==', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_EQUAL) - return result('bin', '==', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_NOT_EQUAL) - return result('bin', '!=', expr, this.next().read_expr()); - if (this.token === '<') - return result('bin', '<', expr, this.next().read_expr()); - if (this.token === '>') - return result('bin', '>', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_SMALLER_OR_EQUAL) - return result('bin', '<=', expr, this.next().read_expr()); - if (this.token === this.tok.T_IS_GREATER_OR_EQUAL) - return result('bin', '>=', expr, this.next().read_expr()); - if (this.token === this.tok.T_SPACESHIP) - return result('bin', '<=>', expr, this.next().read_expr()); - if (this.token === this.tok.T_INSTANCEOF) - return result('bin', 'instanceof', expr, this.next().read_expr()); + if (this.token === this.tok.T_BOOLEAN_OR) { + return result("bin", "||", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_LOGICAL_OR) { + return result("bin", "or", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_BOOLEAN_AND) { + return result("bin", "&&", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_LOGICAL_AND) { + return result("bin", "and", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_LOGICAL_XOR) { + return result("bin", "xor", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_IS_IDENTICAL) { + return result("bin", "===", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_IS_NOT_IDENTICAL) { + return result("bin", "!==", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_IS_EQUAL) { + return result("bin", "==", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_IS_NOT_EQUAL) { + return result("bin", "!=", expr, this.next().read_expr()); + } + if (this.token === "<") { + return result("bin", "<", expr, this.next().read_expr()); + } + if (this.token === ">") { + return result("bin", ">", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_IS_SMALLER_OR_EQUAL) { + return result("bin", "<=", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_IS_GREATER_OR_EQUAL) { + return result("bin", ">=", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_SPACESHIP) { + return result("bin", "<=>", expr, this.next().read_expr()); + } + if (this.token === this.tok.T_OBJECT_OPERATOR) { + if (this.version < 804) { + this.raiseError( + "New without parenthesis is not allowed before PHP 8.4", + ); + } + return result("bin", "->", expr, this.next().read_expr()); + } + + if (this.token === this.tok.T_INSTANCEOF) { + expr = result( + "bin", + "instanceof", + expr, + this.next().read_class_name_reference(), + ); + if ( + this.token !== ";" && + this.token !== this.tok.T_INLINE_HTML && + this.token !== this.EOF + ) { + expr = this.read_expr(expr); + } + } // extra operations : // $username = $_GET['user'] ?? 'nobody'; - if (this.token === this.tok.T_COALESCE) - return result('bin', '??', expr, this.next().read_expr()); + if (this.token === this.tok.T_COALESCE) { + return result("bin", "??", expr, this.next().read_expr()); + } // extra operations : // $username = $_GET['user'] ? true : false; - if (this.token === '?') { - var trueArg = null; - if (this.next().token !== ':') { + if (this.token === "?") { + let trueArg = null; + if (this.next().token !== ":") { trueArg = this.read_expr(); } - this.expect(':') && this.next(); - return result('retif', expr, trueArg, this.read_expr()); + this.expect(":") && this.next(); + return result("retif", expr, trueArg, this.read_expr()); + } else { + // see #193 + result.destroy(expr); } return expr; - } + }, + + /* + * Reads a cast expression + */ + read_expr_cast: function (type) { + return this.node("cast")(type, this.text(), this.next().read_expr()); + }, + + /* + * Read a isset variable + */ + read_isset_variable: function () { + return this.read_expr(); + }, + + /* + * Reads isset variables + */ + read_isset_variables: function () { + return this.read_function_list(this.read_isset_variable, ","); + }, + + /* + * Reads internal PHP functions + */ + read_internal_functions_in_yacc: function () { + let result = null; + switch (this.token) { + case this.tok.T_ISSET: + { + result = this.node("isset"); + if (this.next().expect("(")) { + this.next(); + } + const variables = this.read_isset_variables(); + if (this.expect(")")) { + this.next(); + } + result = result(variables); + } + break; + case this.tok.T_EMPTY: + { + result = this.node("empty"); + if (this.next().expect("(")) { + this.next(); + } + const expression = this.read_expr(); + if (this.expect(")")) { + this.next(); + } + result = result(expression); + } + break; + case this.tok.T_INCLUDE: + result = this.node("include")(false, false, this.next().read_expr()); + break; + case this.tok.T_INCLUDE_ONCE: + result = this.node("include")(true, false, this.next().read_expr()); + break; + case this.tok.T_EVAL: + { + result = this.node("eval"); + if (this.next().expect("(")) { + this.next(); + } + const expr = this.read_expr(); + if (this.expect(")")) { + this.next(); + } + result = result(expr); + } + break; + case this.tok.T_REQUIRE: + result = this.node("include")(false, true, this.next().read_expr()); + break; + case this.tok.T_REQUIRE_ONCE: + result = this.node("include")(true, true, this.next().read_expr()); + break; + } + + return result; + }, + + /* + * Reads optional expression + */ + read_optional_expr: function (stopToken) { + if (this.token !== stopToken) { + return this.read_expr(); + } - /** + return null; + }, + + /* + * Reads exit expression + */ + read_exit_expr: function () { + let expression = null; + + if (this.token === "(") { + this.next(); + expression = this.read_optional_expr(")"); + this.expect(")") && this.next(); + } + + return expression; + }, + + /* * ```ebnf * Reads an expression * expr ::= @todo * ``` */ - ,read_expr_item: function() { - - if (this.token === '@') - return this.node('silent')(this.next().read_expr()); - if (this.token === '+') - return this.node('unary')('+', this.next().read_expr()); - if (this.token === '!') - return this.node('unary')('!', this.next().read_expr()); - if (this.token === '~') - return this.node('unary')('~', this.next().read_expr()); - - if (this.token === '-') { - var result = this.node(); - this.next(); - if ( - this.token === this.tok.T_LNUMBER || - this.token === this.tok.T_DNUMBER - ) { - // negative number - result = result('number', '-' + this.text()); - this.next(); - return result; - } else { - return result('unary', '-', this.read_expr()); - } + read_expr_item: function () { + let result, + expr, + attrs = []; + if (this.token === "+") { + return this.node("unary")("+", this.next().read_expr()); + } + if (this.token === "-") { + return this.node("unary")("-", this.next().read_expr()); + } + if (this.token === "!") { + return this.node("unary")("!", this.next().read_expr()); + } + if (this.token === "~") { + return this.node("unary")("~", this.next().read_expr()); } - if (this.token === '(') { - var node = this.node('parenthesis'); - var expr = this.next().read_expr(); - this.expect(')') && this.next(); - expr = node(expr); - // handle dereferencable - if (this.token === this.tok.T_OBJECT_OPERATOR) { - return this.recursive_variable_chain_scan(expr, false); - } else if (this.token === this.tok.T_CURLY_OPEN || this.token === '[') { - return this.read_dereferencable(expr); - } else if (this.token === '(') { - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118 - return this.node('call')( - expr, this.read_function_argument_list() - ); - } else { - return expr; - } + if (this.token === "(") { + expr = this.next().read_expr(); + expr.parenthesizedExpression = true; + this.expect(")") && this.next(); + return this.handleDereferencable(expr); } - if (this.token === '`') { + if (this.token === "`") { // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1048 - return this.next().read_encapsed_string('`'); + return this.read_encapsed_string("`"); } if (this.token === this.tok.T_LIST) { - var result = this.node('list'), assign = null; - var isInner = this.innerList; + let assign = null; + const isInner = this.innerList; + result = this.node("list"); if (!isInner) { - assign = this.node('assign'); + assign = this.node("assign"); } - if (this.next().expect('(')) { + if (this.next().expect("(")) { this.next(); } if (!this.innerList) this.innerList = true; - var assignList = this.read_assignment_list(); + + // reads inner items + const assignList = this.read_array_pair_list(false); + if (this.expect(")")) { + this.next(); + } // check if contains at least one assignment statement - var hasItem = false; - for(var i = 0; i < assignList.length; i++) { - if (assignList[i] !== null) { + let hasItem = false; + for (let i = 0; i < assignList.length; i++) { + if (assignList[i] !== null && assignList[i].kind !== "noop") { hasItem = true; break; } } if (!hasItem) { + /* istanbul ignore next */ this.raiseError( - 'Fatal Error : Cannot use empty list on line ' + this.lexer.yylloc.first_line + "Fatal Error : Cannot use empty list on line " + + this.lexer.yylloc.first_line, ); } - if (this.expect(')')) { - this.next(); - } + // handles the node resolution if (!isInner) { this.innerList = false; - if (this.expect('=')) { + if (this.expect("=")) { return assign( - result(assignList), + result(assignList, false), this.next().read_expr(), - '=' + "=", ); } else { - // fallback : list($a, $b); - return result(assignList); + // error fallback : list($a, $b); + /* istanbul ignore next */ + return result(assignList, false); } } else { - return result(assignList); + return result(assignList, false); } } - if (this.token === this.tok.T_CLONE) - return this.node('clone')( - this.next().read_expr() - ); + if (this.token === this.tok.T_ATTRIBUTE) { + attrs = this.read_attr_list(); + } - switch(this.token) { + if (this.token === this.tok.T_CLONE) { + return this.node("clone")(this.next().read_expr()); + } + switch (this.token) { case this.tok.T_INC: - return this.node('pre')( - '+', this.next().read_variable(false, false, false) - ); + return this.node("pre")("+", this.next().read_variable(false, false)); case this.tok.T_DEC: - return this.node('pre')( - '-', this.next().read_variable(false, false, false) - ); + return this.node("pre")("-", this.next().read_variable(false, false)); case this.tok.T_NEW: - return this.next().read_new_expr(); + return this.read_new_expr(); case this.tok.T_ISSET: - var result = this.node('isset'); - if (this.next().expect('(')) { - this.next(); - } - var args = this.read_list(this.read_expr, ','); - if (this.expect(')')) { - this.next(); - } - return result(args); - case this.tok.T_EMPTY: - var result = this.node('empty'); - if (this.next().expect('(')) { - this.next(); - } - var arg = this.read_expr(); - if (this.expect(')')) { - this.next(); - } - return result([arg]); - case this.tok.T_INCLUDE: - return this.node('include')( - false, false, - this.next().read_expr() - ); - case this.tok.T_INCLUDE_ONCE: - return this.node('include')( - true, false, - this.next().read_expr() - ); - + case this.tok.T_EVAL: case this.tok.T_REQUIRE: - return this.node('include')( - false, true, - this.next().read_expr() - ); - case this.tok.T_REQUIRE_ONCE: - return this.node('include')( - true, true, - this.next().read_expr() - ); - - case this.tok.T_EVAL: - var result = this.node('eval'); - if (this.next().expect('(')) { - this.next(); - } - var expr = this.read_expr(); - if (this.expect(')')) { - this.next(); - } - return result(expr); + return this.read_internal_functions_in_yacc(); + case this.tok.T_MATCH: + return this.read_match_expression(); case this.tok.T_INT_CAST: - return this.node('cast')('int', this.next().read_expr()); + return this.read_expr_cast("int"); case this.tok.T_DOUBLE_CAST: - return this.node('cast')('double', this.next().read_expr()); + return this.read_expr_cast("float"); case this.tok.T_STRING_CAST: - return this.node('cast')('string', this.next().read_expr()); + return this.read_expr_cast( + this.text().indexOf("binary") !== -1 ? "binary" : "string", + ); case this.tok.T_ARRAY_CAST: - return this.node('cast')('array', this.next().read_expr()); + return this.read_expr_cast("array"); case this.tok.T_OBJECT_CAST: - return this.node('cast')('object', this.next().read_expr()); + return this.read_expr_cast("object"); case this.tok.T_BOOL_CAST: - return this.node('cast')('boolean', this.next().read_expr()); + return this.read_expr_cast("bool"); case this.tok.T_UNSET_CAST: - return this.node('unset')( - this.next().read_expr() - ); + return this.read_expr_cast("unset"); - case this.tok.T_EXIT: - var result = this.node('exit'); - var status = null; - if ( this.next().token === '(' ) { - if (this.next().token !== ')') { - status = this.read_expr(); - if (this.expect(')')) { - this.next(); - } - } else { - this.next(); - } + case this.tok.T_THROW: { + if (this.version < 800) { + this.raiseError("PHP 8+ is required to use throw as an expression"); } - return result(status); + const result = this.node("throw"); + const expr = this.next().read_expr(); + return result(expr); + } + case this.tok.T_EXIT: { + const useDie = this.lexer.yytext.toLowerCase() === "die"; + result = this.node("exit"); + this.next(); + const expression = this.read_exit_expr(); + return result(expression, useDie); + } case this.tok.T_PRINT: - return this.node('print')( - this.next().read_expr() - ); + return this.node("print")(this.next().read_expr()); // T_YIELD (expr (T_DOUBLE_ARROW expr)?)? - case this.tok.T_YIELD: - var result = this.node('yield'), value = null, key = null; - if (this.next().is('EXPR')) { + case this.tok.T_YIELD: { + let value = null; + let key = null; + result = this.node("yield"); + if (this.next().is("EXPR")) { // reads the yield return value value = this.read_expr(); if (this.token === this.tok.T_DOUBLE_ARROW) { @@ -324,235 +429,413 @@ module.exports = { } } return result(value, key); + } // T_YIELD_FROM expr case this.tok.T_YIELD_FROM: - var result = this.node('yieldfrom'); - var expr = this.next().read_expr(); + result = this.node("yieldfrom"); + expr = this.next().read_expr(); return result(expr); + case this.tok.T_FN: case this.tok.T_FUNCTION: - return this.read_function(true); + return this.read_inline_function(undefined, attrs); - case this.tok.T_STATIC: - var backup = [this.token, this.lexer.getState()]; - if (this.next().token === this.tok.T_FUNCTION) { + case this.tok.T_STATIC: { + const backup = [this.token, this.lexer.getState()]; + this.next(); + if ( + this.token === this.tok.T_FUNCTION || + (this.version >= 704 && this.token === this.tok.T_FN) + ) { // handles static function - return this.read_function(true, [0, 1, 0]); + return this.read_inline_function([0, 1, 0], attrs); } else { // rollback this.lexer.tokens.push(backup); this.next(); } - - + } } // SCALAR | VARIABLE - var expr; - if (this.is('VARIABLE')) { - var result = this.node(); - expr = this.read_variable(false, false, false); + if (this.is("VARIABLE")) { + result = this.node(); + expr = this.read_variable(false, false); // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L877 // should accept only a variable - var isConst = ( - expr.kind === 'constref' || ( - expr.kind === 'staticlookup' && - expr.offset.kind === 'constref' - ) - ); + const isConst = + expr.kind === "identifier" || + (expr.kind === "staticlookup" && expr.offset.kind === "identifier"); // VARIABLES SPECIFIC OPERATIONS - switch(this.token) { - case '=': - if (isConst) this.error('VARIABLE'); - var right; - if (this.next().token == '&') { - if (this.next().token === this.tok.T_NEW) { - right = this.next().read_new_expr(); - } else { - right = this.read_variable(false, false, true); - } - } else { - right = this.read_expr(); + switch (this.token) { + case "=": { + if (isConst) this.error("VARIABLE"); + if (this.next().token == "&") { + return this.read_assignref(result, expr); } - return result('assign', expr, right, '='); + return result("assign", expr, this.read_expr(), "="); + } // operations : case this.tok.T_PLUS_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '+='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "+="); case this.tok.T_MINUS_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '-='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "-="); case this.tok.T_MUL_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '*='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "*="); case this.tok.T_POW_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '**='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "**="); case this.tok.T_DIV_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '/='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "/="); case this.tok.T_CONCAT_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '.='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), ".="); case this.tok.T_MOD_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '%='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "%="); case this.tok.T_AND_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '&='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "&="); case this.tok.T_OR_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '|='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "|="); case this.tok.T_XOR_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '^='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "^="); case this.tok.T_SL_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign', expr, this.next().read_expr(), '<<='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "<<="); case this.tok.T_SR_EQUAL: - if (isConst) this.error('VARIABLE'); - return result('assign',expr, this.next().read_expr(), '>>='); + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), ">>="); + + case this.tok.T_COALESCE_EQUAL: + if (isConst) this.error("VARIABLE"); + return result("assign", expr, this.next().read_expr(), "??="); case this.tok.T_INC: - if (isConst) this.error('VARIABLE'); + if (isConst) this.error("VARIABLE"); this.next(); - return result('post', '+', expr); + return result("post", "+", expr); case this.tok.T_DEC: - if (isConst) this.error('VARIABLE'); + if (isConst) this.error("VARIABLE"); this.next(); - return result('post', '-', expr); + return result("post", "-", expr); + default: + // see #193 + result.destroy(expr); } - } else if (this.is('SCALAR')) { + } else if (this.is("SCALAR")) { + result = this.node(); expr = this.read_scalar(); - // handle dereferencable - while(this.token !== this.EOF) { - if (this.token === this.tok.T_OBJECT_OPERATOR) { - expr = this.recursive_variable_chain_scan(expr, false); - } else if (this.token === this.tok.T_CURLY_OPEN || this.token === '[') { - expr = this.read_dereferencable(expr); - } else if (this.token === '(') { - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118 - expr = this.node('call')(expr, this.read_function_argument_list()); - } else { - return expr; - } + if (expr.kind === "array" && expr.shortForm && this.token === "=") { + // list assign + const list = this.convertToList(expr); + if (expr.loc) list.loc = expr.loc; + const right = this.next().read_expr(); + return result("assign", list, right, "="); + } else { + // see #189 - swap docs on nodes + result.destroy(expr); } + // classic array + return this.handleDereferencable(expr); } else { - this.error('EXPR'); + this.error("EXPR"); this.next(); } // returns variable | scalar return expr; + }, - } - /** + /* + * Recursively convert nested array to nested list. + */ + convertToList: function (array) { + const convertedItems = array.items.map((entry) => { + if ( + entry.value && + entry.value.kind === "array" && + entry.value.shortForm + ) { + entry.value = this.convertToList(entry.value); + } + return entry; + }); + const node = this.node("list")(convertedItems, true); + if (array.loc) node.loc = array.loc; + if (array.leadingComments) node.leadingComments = array.leadingComments; + if (array.trailingComments) node.trailingComments = array.trailingComments; + return node; + }, + + /* + * Reads assignment + * @param {*} left + */ + read_assignref: function (result, left) { + this.next(); + let right; + if (this.token === this.tok.T_NEW) { + if (this.version >= 700) { + this.error(); + } + right = this.read_new_expr(); + } else { + right = this.read_variable(false, false); + } + + return result("assignref", left, right); + }, + + /* + * + * inline_function: + * function returns_ref backup_doc_comment '(' parameter_list ')' lexical_vars return_type + * backup_fn_flags '{' inner_statement_list '}' backup_fn_flags + * { $$ = zend_ast_create_decl(ZEND_AST_CLOSURE, $2 | $13, $1, $3, + * zend_string_init("{closure}", sizeof("{closure}") - 1, 0), + * $5, $7, $11, $8); CG(extra_fn_flags) = $9; } + * | fn returns_ref '(' parameter_list ')' return_type backup_doc_comment T_DOUBLE_ARROW backup_fn_flags backup_lex_pos expr backup_fn_flags + * { $$ = zend_ast_create_decl(ZEND_AST_ARROW_FUNC, $2 | $12, $1, $7, + * zend_string_init("{closure}", sizeof("{closure}") - 1, 0), $4, NULL, + * zend_ast_create(ZEND_AST_RETURN, $11), $6); + * ((zend_ast_decl *) $$)->lex_pos = $10; + * CG(extra_fn_flags) = $9; } * + */ + read_inline_function: function (flags, attrs) { + if (this.token === this.tok.T_FUNCTION) { + const result = this.read_function(true, flags, attrs); + result.attrGroups = attrs; + return result; + } + // introduced in PHP 7.4 + if (!this.version >= 704) { + this.raiseError("Arrow Functions are not allowed"); + } + // as an arrowfunc + const node = this.node("arrowfunc"); + // eat T_FN + if (this.expect(this.tok.T_FN)) this.next(); + // check the & + const isRef = this.is_reference(); + // ... + if (this.expect("(")) this.next(); + const params = this.read_parameter_list(); + if (this.expect(")")) this.next(); + let nullable = false; + let returnType = null; + if (this.token === ":") { + if (this.next().token === "?") { + nullable = true; + this.next(); + } + returnType = this.read_types(); + } + if (this.expect(this.tok.T_DOUBLE_ARROW)) this.next(); + const body = this.read_expr(); + const result = node( + params, + isRef, + body, + returnType, + nullable, + flags ? true : false, + ); + result.attrGroups = attrs; + return result; + }, + + read_match_expression: function () { + const node = this.node("match"); + this.expect(this.tok.T_MATCH) && this.next(); + if (this.version < 800) { + this.raiseError("Match statements are not allowed before PHP 8"); + } + let cond = null; + let arms = []; + if (this.expect("(")) this.next(); + cond = this.read_expr(); + if (this.expect(")")) this.next(); + if (this.expect("{")) this.next(); + arms = this.read_match_arms(); + if (this.expect("}")) this.next(); + return node(cond, arms); + }, + + read_match_arms: function () { + return this.read_list(() => this.read_match_arm(), ",", true); + }, + + read_match_arm: function () { + if (this.token === "}") { + return; + } + return this.node("matcharm")(this.read_match_arm_conds(), this.read_expr()); + }, + + read_match_arm_conds: function () { + let conds = []; + if (this.token === this.tok.T_DEFAULT) { + conds = null; + this.next(); + } else { + conds.push(this.read_expr()); + while (this.token === ",") { + this.next(); + if (this.token === this.tok.T_DOUBLE_ARROW) { + this.next(); + return conds; + } + conds.push(this.read_expr()); + } + } + if (this.expect(this.tok.T_DOUBLE_ARROW)) { + this.next(); + } + return conds; + }, + + read_attribute() { + const name = this.text(); + let args = []; + this.next(); + if (this.token === "(") { + args = this.read_argument_list(); + } + return this.node("attribute")(name, args); + }, + read_attr_list() { + const list = []; + if (this.token === this.tok.T_ATTRIBUTE) { + do { + const attrGr = this.node("attrgroup")([]); + this.next(); + attrGr.attrs.push(this.read_attribute()); + while (this.token === ",") { + this.next(); + if (this.token !== "]") attrGr.attrs.push(this.read_attribute()); + } + list.push(attrGr); + this.expect("]"); + this.next(); + } while (this.token === this.tok.T_ATTRIBUTE); + } + return list; + }, + + /* * ```ebnf * new_expr ::= T_NEW (namespace_name function_argument_list) | (T_CLASS ... class declaration) * ``` * https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L850 */ - ,read_new_expr: function() { - var result = this.node('new'); + read_new_expr: function () { + const result = this.node("new"); + this.expect(this.tok.T_NEW) && this.next(); + let args = []; + if (this.token === "(") { + this.next(); + const newExp = this.read_expr(); + this.expect(")"); + this.next(); + if (this.token === "(") { + args = this.read_argument_list(); + } + return result(newExp, args); + } + const attrs = this.read_attr_list(); if (this.token === this.tok.T_CLASS) { - var what = this.node('class'); + const what = this.node("class"); // Annonymous class declaration - var propExtends = null, propImplements = null, body = null, args = []; - if (this.next().token === '(') { - args = this.read_function_argument_list(); - } - if (this.token == this.tok.T_EXTENDS) { - propExtends = this.next().read_namespace_name(); - } - if (this.token == this.tok.T_IMPLEMENTS) { - propImplements = this.next().read_name_list(); - } - if (this.expect('{')) { - body = this.next().read_class_body(); + if (this.next().token === "(") { + args = this.read_argument_list(); } - return result( - what( - null - ,propExtends - ,propImplements - ,body - ,[0, 0, 0] - ), args - ); - } else { - // Already existing class - var name = this.read_class_name_reference(); - var args = []; - if (this.token === '(') { - args = this.read_function_argument_list(); + const propExtends = this.read_extends_from(); + const propImplements = this.read_implements_list(); + let body = null; + if (this.expect("{")) { + body = this.next().read_class_body(true, false); } - return result(name, args); + const whatNode = what(null, propExtends, propImplements, body, [0, 0, 0]); + whatNode.attrGroups = attrs; + return result(whatNode, args); + } + // Already existing class + let name = this.read_new_class_name(); + while (this.token === "[") { + const offsetNode = this.node("offsetlookup"); + const offset = this.next().read_encaps_var_offset(); + this.expect("]") && this.next(); + name = offsetNode(name, offset); + } + if (this.token === "(") { + args = this.read_argument_list(); } - } - /** + return result(name, args); + }, + /* * Reads a class name * ```ebnf - * class_name_reference ::= namespace_name | variable + * read_new_class_name ::= namespace_name | variable * ``` */ - ,read_class_name_reference: function() { + read_new_class_name: function () { if ( this.token === this.tok.T_NS_SEPARATOR || + this.token === this.tok.T_NAME_RELATIVE || + this.token === this.tok.T_NAME_QUALIFIED || + this.token === this.tok.T_NAME_FULLY_QUALIFIED || this.token === this.tok.T_STRING || this.token === this.tok.T_NAMESPACE ) { - var result = this.read_namespace_name(); + let result = this.read_namespace_name(true); if (this.token === this.tok.T_DOUBLE_COLON) { result = this.read_static_getter(result); } return result; - } else if (this.is('VARIABLE')) { - return this.read_variable(true, false, false); + } else if (this.is("VARIABLE")) { + return this.read_variable(true, false); } else { - this.expect([this.tok.T_STRING, 'VARIABLE']); + this.expect([this.tok.T_STRING, "VARIABLE"]); } - } - /** - * ```ebnf - * assignment_list ::= assignment_list_element (',' assignment_list_element?)* - * ``` - */ - ,read_assignment_list: function() { - return this.read_list( - this.read_assignment_list_element, ',' - ); - } - - /** - * ```ebnf - * assignment_list_element ::= expr | expr T_DOUBLE_ARROW expr - * ``` - */ - ,read_assignment_list_element: function() { - if (this.token === ',' || this.token === ')') return null; - var result = this.read_expr_item(); - if (this.token === this.tok.T_DOUBLE_ARROW) { - result = [ - 'key', - result, - this.next().read_expr_item() - ]; + }, + handleDereferencable: function (expr) { + while (this.token !== this.EOF) { + if ( + this.token === this.tok.T_OBJECT_OPERATOR || + this.token === this.tok.T_DOUBLE_COLON + ) { + expr = this.recursive_variable_chain_scan(expr, false, false, true); + } else if (this.token === this.tok.T_CURLY_OPEN || this.token === "[") { + expr = this.read_dereferencable(expr); + } else if (this.token === "(") { + // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1118 + expr = this.node("call")(expr, this.read_argument_list()); + } else { + return expr; + } } - return result; - } + return expr; + }, }; diff --git a/src/parser/function.js b/src/parser/function.js index 2d71de182..314eca2d4 100644 --- a/src/parser/function.js +++ b/src/parser/function.js @@ -1,49 +1,52 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; module.exports = { - /** + /* * checks if current token is a reference keyword */ - is_reference: function() { - if (this.token == '&') { + is_reference: function () { + if (this.token === "&") { this.next(); return true; } return false; - } - /** + }, + /* * checks if current token is a variadic keyword */ - ,is_variadic: function() { + is_variadic: function () { if (this.token === this.tok.T_ELLIPSIS) { this.next(); return true; } return false; - } - /** + }, + /* * reading a function * ```ebnf * function ::= function_declaration code_block * ``` */ - ,read_function: function(closure, flag) { - var result = this.read_function_declaration( - closure ? 1 : (flag ? 2 : 0), - flag && flag[1] === 1 + read_function: function (closure, flag, attrs, locStart) { + const result = this.read_function_declaration( + closure ? 1 : flag ? 2 : 0, + flag && flag[1] === 1, + attrs || [], + locStart, ); if (flag && flag[2] == 1) { // abstract function : result.parseFlags(flag); - if (this.expect(';')) { - this.nextWithComments(); + if (this.expect(";")) { + this.next(); } } else { - if (this.expect('{')) { + if (this.expect("{")) { result.body = this.read_code_block(false); if (result.loc && result.body.loc) { result.loc.end = result.body.loc.end; @@ -54,186 +57,451 @@ module.exports = { } } return result; - } - /** + }, + /* * reads a function declaration (without his body) * ```ebnf * function_declaration ::= T_FUNCTION '&'? T_STRING '(' parameter_list ')' * ``` */ - ,read_function_declaration: function(type, isStatic) { - var nodeName = 'function'; + read_function_declaration: function (type, isStatic, attrs, locStart) { + let nodeName = "function"; if (type === 1) { - nodeName = 'closure'; + nodeName = "closure"; } else if (type === 2) { - nodeName = 'method'; + nodeName = "method"; } - var result = this.node(nodeName); + const result = this.node(nodeName); if (this.expect(this.tok.T_FUNCTION)) { this.next(); } - var isRef = this.is_reference(); - var name = false, use = [], returnType = null, nullable = false; + const isRef = this.is_reference(); + let name = false, + use = [], + returnType = null, + nullable = false; if (type !== 1) { - if (this.expect(this.tok.T_STRING)) { - name = this.text(); - this.next(); + const nameNode = this.node("identifier"); + if (type === 2) { + if (this.version >= 700) { + if (this.token === this.tok.T_STRING || this.is("IDENTIFIER")) { + name = this.text(); + this.next(); + } else if (this.version < 704) { + this.error("IDENTIFIER"); + } + } else if (this.token === this.tok.T_STRING) { + name = this.text(); + this.next(); + } else { + this.error("IDENTIFIER"); + } + } else { + if (this.version >= 700) { + if (this.token === this.tok.T_STRING) { + name = this.text(); + this.next(); + } else if (this.version >= 704) { + if (!this.expect("(")) { + this.next(); + } + } else { + this.error(this.tok.T_STRING); + this.next(); + } + } else { + if (this.expect(this.tok.T_STRING)) { + name = this.text(); + } + this.next(); + } } + name = nameNode(name); } - if (this.expect('(')) this.next(); - var params = this.read_parameter_list(); - if (this.expect(')')) this.next(); - if (type === 1 && this.token === this.tok.T_USE) { - if (this.next().expect('(')) this.next(); - use = this.read_list(this.read_lexical_var, ','); - if (this.expect(')')) this.next(); + if (this.expect("(")) this.next(); + const params = this.read_parameter_list(name.name === "__construct"); + if (this.expect(")")) this.next(); + if (type === 1) { + use = this.read_lexical_vars(); } - if (this.token === ':') { - if (this.next().token === '?') { + if (this.token === ":") { + if (this.next().token === "?") { nullable = true; this.next(); } - returnType = this.read_type(); + returnType = this.read_types(); } + const apply_attrgroup_location = (node) => { + node.attrGroups = attrs || []; + + if (locStart && node.loc) { + node.loc.start = locStart; + if (node.loc.source) { + node.loc.source = this.lexer._input.substr( + node.loc.start.offset, + node.loc.end.offset - node.loc.start.offset, + ); + } + } + return node; + }; + if (type === 1) { // closure - return result(params, isRef, use, returnType, nullable, isStatic); + return apply_attrgroup_location( + result(params, isRef, use, returnType, nullable, isStatic), + ); + } + return apply_attrgroup_location( + result(name, params, isRef, returnType, nullable), + ); + }, + + read_lexical_vars: function () { + let result = []; + + if (this.token === this.tok.T_USE) { + this.next(); + this.expect("(") && this.next(); + result = this.read_lexical_var_list(); + this.expect(")") && this.next(); + } + + return result; + }, + + read_list_with_dangling_comma: function (item) { + const result = []; + + while (this.token != this.EOF) { + result.push(item()); + if (this.token == ",") { + this.next(); + if (this.version >= 800 && this.token === ")") { + return result; + } + } else if (this.token == ")") { + break; + } else { + this.error([",", ")"]); + break; + } } - return result(name, params, isRef, returnType, nullable); - } - /** + return result; + }, + + read_lexical_var_list: function () { + return this.read_list_with_dangling_comma(this.read_lexical_var.bind(this)); + }, + + /* * ```ebnf * lexical_var ::= '&'? T_VARIABLE * ``` */ - ,read_lexical_var: function() { - var result = this.node('variable'); - var isRef = false; - if (this.token === '&') { - isRef = true; - this.next(); + read_lexical_var: function () { + if (this.token === "&") { + return this.read_byref(this.read_lexical_var.bind(this)); } + const result = this.node("variable"); this.expect(this.tok.T_VARIABLE); - var name = this.text().substring(1); + const name = this.text().substring(1); this.next(); - return result(name, isRef, false); - } - /** + return result(name, false); + }, + /* * reads a list of parameters * ```ebnf * parameter_list ::= (parameter ',')* parameter? * ``` */ - ,read_parameter_list: function() { - var result = []; - if (this.token != ')') { - while(this.token != this.EOF) { - result.push(this.read_parameter()); - if (this.token == ',') { - this.next(); - } else if (this.token == ')') { - break; - } else { - this.error([',', ')']); - break; - } - } + read_parameter_list: function (is_class_constructor) { + if (this.token !== ")") { + let wasVariadic = false; + + return this.read_list_with_dangling_comma( + function () { + const parameter = this.read_parameter(is_class_constructor); + if (parameter) { + // variadic parameters can only be defined at the end of the parameter list + if (wasVariadic) { + this.raiseError( + "Unexpected parameter after a variadic parameter", + ); + } + if (parameter.variadic) { + wasVariadic = true; + } + } + return parameter; + }.bind(this), + ",", + ); } - return result; - } - /** + + return []; + }, + /* * ```ebnf * parameter ::= type? '&'? T_ELLIPSIS? T_VARIABLE ('=' expr)? * ``` * @see https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L640 */ - ,read_parameter: function() { - var node = this.node('parameter'), - name = null, - value = null, - type = null, - nullable = false; - if (this.token === '?') { + read_parameter: function (is_class_constructor) { + const node = this.node("parameter"); + let parameterName = null; + let value = null; + let types = null; + let nullable = false; + let readonly = false; + let attrs = []; + if (this.token === this.tok.T_ATTRIBUTE) attrs = this.read_attr_list(); + + if (this.version >= 801 && this.token === this.tok.T_READ_ONLY) { + if (is_class_constructor) { + this.next(); + readonly = true; + } else { + this.raiseError( + "readonly properties can be used only on class constructor", + ); + } + } + + const flags = this.read_promoted(); + + if ( + !readonly && + this.version >= 801 && + this.token === this.tok.T_READ_ONLY + ) { + if (is_class_constructor) { + this.next(); + readonly = true; + } else { + this.raiseError( + "readonly properties can be used only on class constructor", + ); + } + } + + if (this.token === "?") { this.next(); nullable = true; } - type = this.read_type(); - if (nullable && !type) { - this.raiseError('Expecting a type definition combined with nullable operator'); + types = this.read_types(); + if (nullable && !types) { + this.raiseError( + "Expecting a type definition combined with nullable operator", + ); } - var isRef = this.is_reference(); - var isVariadic = this.is_variadic(); + const isRef = this.is_reference(); + const isVariadic = this.is_variadic(); if (this.expect(this.tok.T_VARIABLE)) { - name = this.text().substring(1); + parameterName = this.node("identifier"); + const name = this.text().substring(1); this.next(); + parameterName = parameterName(name); } - if (this.token == '=') { + if (this.token == "=") { value = this.next().read_expr(); } - return node(name, type, value, isRef, isVariadic, nullable); - } - /** + const result = node( + parameterName, + types, + value, + isRef, + isVariadic, + readonly, + nullable, + flags, + ); + if (attrs) result.attrGroups = attrs; + return result; + }, + read_types: function () { + const MODE_UNSET = "unset"; + const MODE_UNION = "union"; + const MODE_INTERSECTION = "intersection"; + + const types = []; + let mode = MODE_UNSET; + const type = this.read_type(); + if (!type) return null; + + // we have matched a single type + types.push(type); + + // is the current token a: + // - | for union type + // - & for intersection type (> php 8.1) + while (this.token === "|" || (this.version >= 801 && this.token === "&")) { + const nextToken = this.peek(); + + if ( + nextToken === this.tok.T_ELLIPSIS || + nextToken === this.tok.T_VARIABLE + ) { + // the next token is part of the variable (or the variable itself), + // we're not gonna match anymore types + break; + } + + if (mode === MODE_UNSET) { + // are we in union or intersection "mode" + mode = this.token === "|" ? MODE_UNION : MODE_INTERSECTION; + } else { + // it is not possible to mix "modes" + if ( + (mode === MODE_UNION && this.token !== "|") || + (mode === MODE_INTERSECTION && this.token !== "&") + ) { + this.raiseError( + 'Unexpect token "' + this.token + '", "|" and "&" can not be mixed', + ); + } + } + + this.next(); + types.push(this.read_type()); + } + if (types.length === 1) { + return types[0]; + } else { + return mode === MODE_INTERSECTION + ? this.node("intersectiontype")(types) + : this.node("uniontype")(types); + } + }, + read_promoted: function () { + const MODIFIER_PUBLIC = 1; + const MODIFIER_PROTECTED = 2; + const MODIFIER_PRIVATE = 4; + if (this.token === this.tok.T_PUBLIC) { + this.next(); + return MODIFIER_PUBLIC; + } else if (this.token === this.tok.T_PROTECTED) { + this.next(); + return MODIFIER_PROTECTED; + } else if (this.token === this.tok.T_PRIVATE) { + this.next(); + return MODIFIER_PRIVATE; + } + return 0; + }, + /* * Reads a list of arguments * ```ebnf * function_argument_list ::= '(' (argument_list (',' argument_list)*)? ')' * ``` */ - ,read_function_argument_list: function() { - var result = []; - var wasVariadic = false; - this.expect('(') && this.next(); - if (this.token !== ')') { - while(this.token != this.EOF) { - var argument = this.read_argument_list(); + read_argument_list: function () { + let result = []; + this.expect("(") && this.next(); + if ( + this.version >= 801 && + this.token === this.tok.T_ELLIPSIS && + this.peek() === ")" + ) { + result.push(this.node("variadicplaceholder")()); + this.next(); + } else if (this.token !== ")") { + result = this.read_non_empty_argument_list(); + } + this.expect(")") && this.next(); + return result; + }, + /* + * Reads non empty argument list + */ + read_non_empty_argument_list: function () { + let wasVariadic = false; + + return this.read_function_list( + function () { + const argument = this.read_argument(); if (argument) { - result.push(argument); - if (argument.kind === 'variadic') { + const isVariadic = argument.kind === "variadic"; + // variadic arguments can only be followed by other variadic arguments + if (wasVariadic && !isVariadic) { + this.raiseError( + "Unexpected non-variadic argument after a variadic argument", + ); + } + if (isVariadic) { wasVariadic = true; - } else if (wasVariadic) { - this.raiseError('Unexpected argument after a variadic argument'); } } - if (this.token === ',') { - this.next(); - } else break; - } - } - this.expect(')') && this.next(); - return result; - } - /** + return argument; + }.bind(this), + ",", + ); + }, + /* * ```ebnf - * argument_list ::= T_ELLIPSIS? expr + * argument_list ::= T_STRING ':' expr | T_ELLIPSIS? expr * ``` */ - ,read_argument_list: function() { - if (this.token === this.tok.T_ELLIPSIS ) { - return this.node('variadic')(this.next().read_expr()); + read_argument: function () { + if (this.token === this.tok.T_ELLIPSIS) { + return this.node("variadic")(this.next().read_expr()); + } + if ( + this.token === this.tok.T_STRING || + Object.values(this.lexer.keywords).includes(this.token) + ) { + const nextToken = this.peek(); + if (nextToken === ":") { + if (this.version < 800) { + this.raiseError("PHP 8+ is required to use named arguments"); + } + return this.node("namedargument")( + this.text(), + this.next().next().read_expr(), + ); + } } return this.read_expr(); - } - /** + }, + /* * read type hinting * ```ebnf * type ::= T_ARRAY | T_CALLABLE | namespace_name * ``` */ - ,read_type: function() { - var result = this.node('identifier'); - switch(this.token) { - case this.tok.T_ARRAY: + read_type: function () { + const result = this.node(); + if (this.token === this.tok.T_ARRAY || this.token === this.tok.T_CALLABLE) { + const type = this.text(); + this.next(); + return result("typereference", type.toLowerCase(), type); + } else if ( + this.token === this.tok.T_NAME_RELATIVE || + this.token === this.tok.T_NAME_QUALIFIED || + this.token === this.tok.T_NAME_FULLY_QUALIFIED || + this.token === this.tok.T_STRING || + this.token === this.tok.T_STATIC + ) { + const type = this.text(); + const backup = [this.token, this.lexer.getState()]; + this.next(); + if ( + this.token !== this.tok.T_NS_SEPARATOR && + this.ast.typereference.types.indexOf(type.toLowerCase()) > -1 + ) { + return result("typereference", type.toLowerCase(), type); + } else { + // rollback a classic namespace + this.lexer.tokens.push(backup); this.next(); - return result(['', 'array'], false); - case this.tok.T_NAMESPACE: - case this.tok.T_NS_SEPARATOR: - case this.tok.T_STRING: + // fix : destroy not consumed node (release comments) + result.destroy(); return this.read_namespace_name(); - case this.tok.T_CALLABLE: - this.next(); - return result(['', 'callable'], false); - default: - return null; + } } - } + // fix : destroy not consumed node (release comments) + result.destroy(); + return null; + }, }; diff --git a/src/parser/if.js b/src/parser/if.js index 3731addb5..fda94ee19 100644 --- a/src/parser/if.js +++ b/src/parser/if.js @@ -1,36 +1,36 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; module.exports = { - /** + /* * Reads an IF statement * * ```ebnf * if ::= T_IF '(' expr ')' ':' ... * ``` */ - read_if: function() { - var result = this.node('if'), - body = null, - alternate = null, - shortForm = false, - test = null; - test = this.read_if_expr(); + read_if: function () { + const result = this.node("if"); + const test = this.next().read_if_expr(); + let body = null; + let alternate = null; + let shortForm = false; - if (this.token === ':') { + if (this.token === ":") { shortForm = true; this.next(); - body = this.node('block'); - var items = []; - while(this.token !== this.EOF && this.token !== this.tok.T_ENDIF) { + body = this.node("block"); + const items = []; + while (this.token !== this.EOF && this.token !== this.tok.T_ENDIF) { if (this.token === this.tok.T_ELSEIF) { - alternate = this.next().read_elseif_short(); + alternate = this.read_elseif_short(); break; } else if (this.token === this.tok.T_ELSE) { - alternate = this.next().read_else_short(); + alternate = this.read_else_short(); break; } items.push(this.read_inner_statement()); @@ -40,61 +40,55 @@ module.exports = { this.expectEndOfStatement(); } else { body = this.read_statement(); - /** - * ignore : if (..) { } /* *./ else { } - */ - this.ignoreComments(); if (this.token === this.tok.T_ELSEIF) { - alternate = this.next().read_if(); + alternate = this.read_if(); } else if (this.token === this.tok.T_ELSE) { alternate = this.next().read_statement(); } } return result(test, body, alternate, shortForm); }, - /** + /* * reads an if expression : '(' expr ')' */ - read_if_expr: function() { - this.expect('(') && this.next(); - var result = this.read_expr(); - this.expect(')') && this.next(); + read_if_expr: function () { + this.expect("(") && this.next(); + const result = this.read_expr(); + this.expect(")") && this.next(); return result; }, - /** + /* * reads an elseif (expr): statements */ - read_elseif_short: function() { - var result = this.node('if'), - alternate = null, - test = null, - body = null, - items = []; - test = this.read_if_expr(); - if (this.expect(':')) this.next(); - body = this.node('block'); - while(this.token != this.EOF && this.token !== this.tok.T_ENDIF) { + read_elseif_short: function () { + let alternate = null; + const result = this.node("if"); + const test = this.next().read_if_expr(); + if (this.expect(":")) this.next(); + const body = this.node("block"); + const items = []; + while (this.token != this.EOF && this.token !== this.tok.T_ENDIF) { if (this.token === this.tok.T_ELSEIF) { - alternate = this.next().read_elseif_short(); + alternate = this.read_elseif_short(); break; } else if (this.token === this.tok.T_ELSE) { - alternate = this.next().read_else_short(); + alternate = this.read_else_short(); break; } items.push(this.read_inner_statement()); } - body = body(null, items); - return result(test, body, alternate, true); + return result(test, body(null, items), alternate, true); }, - /** + /* * */ - read_else_short: function() { - if (this.expect(':')) this.next(); - var body = this.node('block'), items = []; - while(this.token != this.EOF && this.token !== this.tok.T_ENDIF) { + read_else_short: function () { + if (this.next().expect(":")) this.next(); + const body = this.node("block"); + const items = []; + while (this.token != this.EOF && this.token !== this.tok.T_ENDIF) { items.push(this.read_inner_statement()); } return body(null, items); - } + }, }; diff --git a/src/parser/loops.js b/src/parser/loops.js index 325005a56..62847a6b8 100644 --- a/src/parser/loops.js +++ b/src/parser/loops.js @@ -1,11 +1,12 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; + module.exports = { - /** + /* * Reads a while statement * ```ebnf * while ::= T_WHILE (statement | ':' inner_statement_list T_ENDWHILE ';') @@ -13,24 +14,24 @@ module.exports = { * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L587 * @return {While} */ - read_while: function() { - var result = this.node('while'), - test = null, - body = null, - shortForm = false - ; - if (this.expect('(')) this.next(); + read_while: function () { + const result = this.node("while"); + this.expect(this.tok.T_WHILE) && this.next(); + let test = null; + let body = null; + let shortForm = false; + if (this.expect("(")) this.next(); test = this.read_expr(); - if (this.expect(')')) this.next(); - if (this.token === ':') { + if (this.expect(")")) this.next(); + if (this.token === ":") { shortForm = true; body = this.read_short_form(this.tok.T_ENDWHILE); } else { body = this.read_statement(); } return result(test, body, shortForm); - } - /** + }, + /* * Reads a do / while loop * ```ebnf * do ::= T_DO statement T_WHILE '(' expr ')' ';' @@ -38,21 +39,21 @@ module.exports = { * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L423 * @return {Do} */ - ,read_do: function() { - var result = this.node('do'), - test = null, - body = null - ; + read_do: function () { + const result = this.node("do"); + this.expect(this.tok.T_DO) && this.next(); + let test = null; + let body = null; body = this.read_statement(); - if (this.ignoreComments().expect(this.tok.T_WHILE)) { - if (this.next().expect('(')) this.next(); - test = this.read_expr(); - if (this.expect(')')) this.next(); - if (this.expect(';')) this.next(); + if (this.expect(this.tok.T_WHILE)) { + if (this.next().expect("(")) this.next(); + test = this.read_expr(); + if (this.expect(")")) this.next(); + if (this.expect(";")) this.next(); } return result(test, body); - } - /** + }, + /* * Read a for incremental loop * ```ebnf * for ::= T_FOR '(' for_exprs ';' for_exprs ';' for_exprs ')' for_statement @@ -62,41 +63,42 @@ module.exports = { * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L425 * @return {For} */ - ,read_for: function() { - var result = this.node('for'), - init = [], - test = [], - increment = [], - body = null, - shortForm = false; - if (this.expect('(')) this.next(); - if (this.token !== ';') { - init = this.read_list(this.read_expr, ','); - if (this.expect(';')) this.next(); + read_for: function () { + const result = this.node("for"); + this.expect(this.tok.T_FOR) && this.next(); + let init = []; + let test = []; + let increment = []; + let body = null; + let shortForm = false; + if (this.expect("(")) this.next(); + if (this.token !== ";") { + init = this.read_list(this.read_expr, ","); + if (this.expect(";")) this.next(); } else { this.next(); } - if (this.token !== ';') { - test = this.read_list(this.read_expr, ','); - if (this.expect(';')) this.next(); + if (this.token !== ";") { + test = this.read_list(this.read_expr, ","); + if (this.expect(";")) this.next(); } else { this.next(); } - if (this.token !== ')') { - increment = this.read_list(this.read_expr, ','); - if (this.expect(')')) this.next(); + if (this.token !== ")") { + increment = this.read_list(this.read_expr, ","); + if (this.expect(")")) this.next(); } else { this.next(); } - if (this.token === ':') { + if (this.token === ":") { shortForm = true; body = this.read_short_form(this.tok.T_ENDFOR); - } else { + } else { body = this.read_statement(); } return result(init, test, increment, body, shortForm); - } - /** + }, + /* * Reads a foreach loop * ```ebnf * foreach ::= '(' expr T_AS foreach_variable (T_DOUBLE_ARROW foreach_variable)? ')' statement @@ -104,16 +106,17 @@ module.exports = { * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L438 * @return {Foreach} */ - ,read_foreach: function() { - var result = this.node('foreach'), - source = null, - key = null, - value = null, - body = null, - shortForm = false; - if (this.expect('(')) this.next(); + read_foreach: function () { + const result = this.node("foreach"); + this.expect(this.tok.T_FOREACH) && this.next(); + let source = null; + let key = null; + let value = null; + let body = null; + let shortForm = false; + if (this.expect("(")) this.next(); source = this.read_expr(); - if (this.ignoreComments().expect(this.tok.T_AS)) { + if (this.expect(this.tok.T_AS)) { this.next(); value = this.read_foreach_variable(); if (this.token === this.tok.T_DOUBLE_ARROW) { @@ -122,37 +125,44 @@ module.exports = { } } - if (this.expect(')')) this.next(); + // grammatically correct but not supported by PHP + if (key && key.kind === "list") { + this.raiseError("Fatal Error : Cannot use list as key element"); + } + + if (this.expect(")")) this.next(); - if (this.token === ':') { + if (this.token === ":") { shortForm = true; body = this.read_short_form(this.tok.T_ENDFOREACH); } else { body = this.read_statement(); } return result(source, key, value, body, shortForm); - } - /** + }, + /* * Reads a foreach variable statement * ```ebnf - * foreach_variable = variable | - * T_LIST '(' assignment_list ')' | - * '[' array_pair_list ']' + * foreach_variable = + * variable | + * '&' variable | + * T_LIST '(' assignment_list ')' | + * '[' assignment_list ']' * ``` * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L544 * @return {Expression} */ - ,read_foreach_variable: function() { - if (this.token === this.tok.T_LIST) { - var result = this.node('list'); - if (this.next().expect('(')) this.next(); - var assignList = this.read_assignment_list(); - if (this.expect(')')) this.next(); - return result(assignList); - } else if (this.token === '[' || this.token === this.tok.T_ARRAY) { - return this.read_array(); - } else { - return this.read_variable(false, false, false); - } - } + read_foreach_variable: function () { + if (this.token === this.tok.T_LIST || this.token === "[") { + const isShort = this.token === "["; + const result = this.node("list"); + this.next(); + if (!isShort && this.expect("(")) this.next(); + const assignList = this.read_array_pair_list(isShort); + if (this.expect(isShort ? "]" : ")")) this.next(); + return result(assignList, isShort); + } else { + return this.read_variable(false, false); + } + }, }; diff --git a/src/parser/main.js b/src/parser/main.js index 27e9920d5..8b18dfff8 100644 --- a/src/parser/main.js +++ b/src/parser/main.js @@ -1,20 +1,21 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; module.exports = { - /** + /* * ```ebnf * start ::= (namespace | top_statement)* * ``` */ - read_start: function() { + read_start: function () { if (this.token == this.tok.T_NAMESPACE) { return this.read_namespace(); } else { return this.read_top_statement(); } - } + }, }; diff --git a/src/parser/namespace.js b/src/parser/namespace.js index 496067b5e..5f1e30431 100644 --- a/src/parser/namespace.js +++ b/src/parser/namespace.js @@ -1,12 +1,12 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; module.exports = { - /** + /* * Reads a namespace declaration block * ```ebnf * namespace ::= T_NAMESPACE namespace_name? '{' @@ -17,63 +17,91 @@ module.exports = { * @see http://php.net/manual/en/language.namespaces.php * @return {Namespace} */ - read_namespace: function() { - var result = this.node('namespace'); + read_namespace: function () { + const result = this.node("namespace"); + let body; this.expect(this.tok.T_NAMESPACE) && this.next(); - if (this.token == '{') { - this.currentNamespace = ['']; - var body = this.nextWithComments().read_top_statements(); - this.expect('}') && this.nextWithComments(); - return result([''], body, true); + let name; + + if (this.token === "{") { + name = { + name: [""], + }; } else { - var name = this.read_namespace_name(); - if (this.token == ';') { - this.currentNamespace = name; - var body = this.nextWithComments().read_top_statements(); - this.expect(this.EOF); - return result(name.name, body, false); - } else if (this.token == '{') { - this.currentNamespace = name; - var body = this.nextWithComments().read_top_statements(); - this.expect('}') && this.nextWithComments(); - return result(name.name, body, true); - } else if (this.token === '(') { - // resolve ambuiguity between namespace & function call - name.resolution = this.ast.identifier.RELATIVE_NAME; - name.name = name.name.substring(1); - return this.node('call')( - name, this.read_function_argument_list() - ); - } else { - this.error(['{', ';']); - // graceful mode : - this.currentNamespace = name; - var body = this.read_top_statements(); - this.expect(this.EOF); - return result(name, body, false); + name = this.read_namespace_name(); + } + this.currentNamespace = name; + + if (this.token === ";") { + this.currentNamespace = name; + body = this.next().read_top_statements(); + this.expect(this.EOF); + return result(name.name, body, false); + } else if (this.token === "{") { + this.currentNamespace = name; + body = this.next().read_top_statements(); + this.expect("}") && this.next(); + if ( + body.length === 0 && + this.extractDoc && + this._docs.length > this._docIndex + ) { + body.push(this.node("noop")()); } + return result(name.name, body, true); + } else { + this.error(["{", ";"]); + // graceful mode : + this.currentNamespace = name; + body = this.read_top_statements(); + this.expect(this.EOF); + return result(name, body, false); } - } - /** + }, + /* * Reads a namespace name * ```ebnf * namespace_name ::= T_NS_SEPARATOR? (T_STRING T_NS_SEPARATOR)* T_STRING * ``` * @see http://php.net/manual/en/language.namespaces.rules.php - * @return {Identifier} + * @return {Reference} */ - ,read_namespace_name: function() { - var result = this.node('identifier'), relative = false; - if (this.token === this.tok.T_NAMESPACE) { - this.next().expect(this.tok.T_NS_SEPARATOR) && this.next(); - relative = true + read_namespace_name: function (resolveReference) { + const result = this.node(); + let resolution; + let name = this.text(); + switch (this.token) { + case this.tok.T_NAME_RELATIVE: + resolution = this.ast.name.RELATIVE_NAME; + name = name.replace(/^namespace\\/, ""); + break; + case this.tok.T_NAME_QUALIFIED: + resolution = this.ast.name.QUALIFIED_NAME; + break; + case this.tok.T_NAME_FULLY_QUALIFIED: + resolution = this.ast.name.FULL_QUALIFIED_NAME; + break; + default: + resolution = this.ast.name.UNQUALIFIED_NAME; + if (!this.expect(this.tok.T_STRING)) { + // graceful mode + return result("name", "", this.ast.name.FULL_QUALIFIED_NAME); + } + } + + this.next(); + + if (resolveReference || this.token !== "(") { + if (name.toLowerCase() === "parent") { + return result("parentreference", name); + } else if (name.toLowerCase() === "self") { + return result("selfreference", name); + } } - return result( - this.read_list(this.tok.T_STRING, this.tok.T_NS_SEPARATOR, true), - relative - ); - } - /** + + return result("name", name, resolution); + }, + /* * Reads a use statement * ```ebnf * use_statement ::= T_USE @@ -85,26 +113,33 @@ module.exports = { * @see http://php.net/manual/en/language.namespaces.importing.php * @return {UseGroup} */ - ,read_use_statement: function() { - var result = this.node('usegroup'), - type = null, - items = [], - name = null - ; + read_use_statement: function () { + let result = this.node("usegroup"); + let items = []; + let name = null; this.expect(this.tok.T_USE) && this.next(); - type = this.read_use_type(); + const type = this.read_use_type(); items.push(this.read_use_declaration(false)); - if (this.token === ',') { + if (this.token === ",") { items = items.concat(this.next().read_use_declarations(false)); - } else if (this.token === '{') { + } else if (this.token === "{") { name = items[0].name; items = this.next().read_use_declarations(type === null); - this.expect('}') && this.next(); + this.expect("}") && this.next(); } - this.expect(';') && this.nextWithComments(); - return result(name, type, items); - } - /** + result = result(name, type, items); + this.expect(";") && this.next(); + return result; + }, + /* + * + * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1045 + */ + read_class_name_reference: function () { + // resolved as the same + return this.read_variable(true, false); + }, + /* * Reads a use declaration * ```ebnf * use_declaration ::= use_type? namespace_name use_alias @@ -112,46 +147,70 @@ module.exports = { * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L380 * @return {UseItem} */ - ,read_use_declaration: function(typed) { - var result = this.node('useitem'), type = null; + read_use_declaration: function (typed) { + const result = this.node("useitem"); + let type = null; if (typed) type = this.read_use_type(); - var name = this.read_namespace_name(); - var alias = this.read_use_alias(); + const name = this.read_namespace_name(); + const alias = this.read_use_alias(); return result(name.name, alias, type); - } - /** - * Reads a list of use declarations - * ```ebnf - * use_declarations ::= use_declaration (',' use_declaration)* - * ``` - * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L380 - * @return {UseItem[]} + }, + /* + * Reads a list of use declarations + * ```ebnf + * use_declarations ::= use_declaration (',' use_declaration)* + * ``` + * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L380 + * @return {UseItem[]} */ - ,read_use_declarations: function(typed) { - var result = [this.read_use_declaration(typed)]; - while(this.token === ',') { - result.push(this.next().read_use_declaration(typed)); + read_use_declarations: function (typed) { + const result = [this.read_use_declaration(typed)]; + while (this.token === ",") { + this.next(); + if (typed) { + if ( + this.token !== this.tok.T_NAME_RELATIVE && + this.token !== this.tok.T_NAME_QUALIFIED && + this.token !== this.tok.T_NAME_FULLY_QUALIFIED && + this.token !== this.tok.T_FUNCTION && + this.token !== this.tok.T_CONST && + this.token !== this.tok.T_STRING + ) { + break; + } + } else if ( + this.token !== this.tok.T_NAME_RELATIVE && + this.token !== this.tok.T_NAME_QUALIFIED && + this.token !== this.tok.T_NAME_FULLY_QUALIFIED && + this.token !== this.tok.T_STRING && + this.token !== this.tok.T_NS_SEPARATOR + ) { + break; + } + result.push(this.read_use_declaration(typed)); } return result; - } - /** + }, + /* * Reads a use statement * ```ebnf * use_alias ::= (T_AS T_STRING)? * ``` * @return {String|null} */ - ,read_use_alias: function() { - var result = null; + read_use_alias: function () { + let result = null; if (this.token === this.tok.T_AS) { if (this.next().expect(this.tok.T_STRING)) { - result = this.text(); + const aliasName = this.node("identifier"); + const name = this.text(); this.next(); + result = aliasName(name); } } return result; - } - /** + }, + /* * Reads the namespace type declaration * ```ebnf * use_type ::= (T_FUNCTION | T_CONST)? @@ -159,7 +218,7 @@ module.exports = { * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L335 * @return {String|null} Possible values : function, const */ - ,read_use_type: function() { + read_use_type: function () { if (this.token === this.tok.T_FUNCTION) { this.next(); return this.ast.useitem.TYPE_FUNCTION; @@ -168,5 +227,5 @@ module.exports = { return this.ast.useitem.TYPE_CONST; } return null; - } + }, }; diff --git a/src/parser/scalar.js b/src/parser/scalar.js index 147f7ebcc..f8ccea1f6 100644 --- a/src/parser/scalar.js +++ b/src/parser/scalar.js @@ -1,35 +1,203 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -var specialChar = { - '\\r': "\r", - '\\n': "\n", - '\\t': "\t", - '\\v': String.fromCharCode(11), - '\\e': String.fromCharCode(27), - '\\f': String.fromCharCode(12), - "\\\\": "\\", - '\\$': "$", - '\\"': '"', - '\\\'': "'" +const specialChar = { + "\\": "\\", + $: "$", + n: "\n", + r: "\r", + t: "\t", + f: String.fromCharCode(12), + v: String.fromCharCode(11), + e: String.fromCharCode(27), }; module.exports = { - /** + /* * Unescape special chars */ - resolve_special_chars: function(text) { - return text.replace( - /\\[rntvef"'\\\$]/g, - function(seq) { - return specialChar[seq]; - } + resolve_special_chars: function (text, doubleQuote) { + if (!doubleQuote) { + // single quote fix + return text.replace(/\\\\/g, "\\").replace(/\\'/g, "'"); + } + return text + .replace(/\\"/, '"') + .replace( + /\\([\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u{([0-9a-fA-F]+)})/g, + ($match, p1, p2) => { + if (specialChar[p1]) { + return specialChar[p1]; + } else if ("x" === p1[0] || "X" === p1[0]) { + return String.fromCodePoint(parseInt(p1.substr(1), 16)); + } else if ("u" === p1[0]) { + return String.fromCodePoint(parseInt(p2, 16)); + } else { + return String.fromCodePoint(parseInt(p1, 8)); + } + }, + ); + }, + + /* + * Remove all leading spaces each line for heredoc text if there is a indentation + * @param {string} text + * @param {number} indentation + * @param {boolean} indentation_uses_spaces + * @param {boolean} first_encaps_node if it is behind a variable, the first N spaces should not be removed + */ + remove_heredoc_leading_whitespace_chars: function ( + text, + indentation, + indentation_uses_spaces, + first_encaps_node, + ) { + if (indentation === 0) { + return text; + } + + this.check_heredoc_indentation_level( + text, + indentation, + indentation_uses_spaces, + first_encaps_node, + ); + + const matchedChar = indentation_uses_spaces ? " " : "\t"; + const removementRegExp = new RegExp( + `\\n${matchedChar}{${indentation}}`, + "g", ); + const removementFirstEncapsNodeRegExp = new RegExp( + `^${matchedChar}{${indentation}}`, + ); + + // Rough replace, need more check + if (first_encaps_node) { + // Remove text leading whitespace + text = text.replace(removementFirstEncapsNodeRegExp, ""); + } + + // Remove leading whitespace after \n + return text.replace(removementRegExp, "\n"); }, - /** + + /* + * Check indentation level of heredoc in text, if mismatch, raiseError + * @param {string} text + * @param {number} indentation + * @param {boolean} indentation_uses_spaces + * @param {boolean} first_encaps_node if it is behind a variable, the first N spaces should not be removed + */ + check_heredoc_indentation_level: function ( + text, + indentation, + indentation_uses_spaces, + first_encaps_node, + ) { + const textSize = text.length; + let offset = 0; + let leadingWhitespaceCharCount = 0; + /* + * @var inCoutingState {boolean} reset to true after a new line + * @private + */ + let inCoutingState = true; + const chToCheck = indentation_uses_spaces ? " " : "\t"; + let inCheckState = false; + if (!first_encaps_node) { + // start from first \n + offset = text.indexOf("\n"); + // if no \n, just return + if (offset === -1) { + return; + } + offset++; + } + while (offset < textSize) { + if (inCoutingState) { + if (text[offset] === chToCheck) { + leadingWhitespaceCharCount++; + } else { + inCheckState = true; + } + } else { + inCoutingState = false; + } + + if ( + text[offset] !== "\n" && + inCheckState && + leadingWhitespaceCharCount < indentation + ) { + this.raiseError( + `Invalid body indentation level (expecting an indentation at least ${indentation})`, + ); + } else { + inCheckState = false; + } + + if (text[offset] === "\n") { + // Reset counting state + inCoutingState = true; + leadingWhitespaceCharCount = 0; + } + offset++; + } + }, + + /* + * Reads dereferencable scalar + */ + read_dereferencable_scalar: function () { + let result = null; + + switch (this.token) { + case this.tok.T_CONSTANT_ENCAPSED_STRING: + { + let value = this.node("string"); + const text = this.text(); + let offset = 0; + if (text[0] === "b" || text[0] === "B") { + offset = 1; + } + const isDoubleQuote = text[offset] === '"'; + this.next(); + const textValue = this.resolve_special_chars( + text.substring(offset + 1, text.length - 1), + isDoubleQuote, + ); + value = value( + isDoubleQuote, + textValue, + offset === 1, // unicode flag + text, + ); + if (this.token === this.tok.T_DOUBLE_COLON) { + // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1151 + result = this.read_static_getter(value); + } else { + // dirrect string + result = value; + } + } + break; + case this.tok.T_ARRAY: // array parser + result = this.read_array(); + break; + case "[": // short array format + result = this.read_array(); + break; + } + + return result; + }, + + /* * ```ebnf * scalar ::= T_MAGIC_CONST * | T_LNUMBER | T_DNUMBER @@ -39,102 +207,107 @@ module.exports = { * | namespace_name (T_DOUBLE_COLON T_STRING)? * ``` */ - read_scalar: function() { - if (this.is('T_MAGIC_CONST')) { + read_scalar: function () { + if (this.is("T_MAGIC_CONST")) { return this.get_magic_constant(); } else { - switch(this.token) { - - // TEXTS - case this.tok.T_CONSTANT_ENCAPSED_STRING: - var value = this.node('string'); - var text = this.text(); - var isDoubleQuote = text[0] === '"'; - text = text.substring(1, text.length - 1); + let value, node; + switch (this.token) { + // NUMERIC + case this.tok.T_LNUMBER: // long + case this.tok.T_DNUMBER: { + // double + const result = this.node("number"); + value = this.text(); this.next(); - value = value(isDoubleQuote, this.resolve_special_chars(text)); - if (this.token === this.tok.T_DOUBLE_COLON) { - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1151 - return this.read_static_getter(value); - } else { - // dirrect string - return value; - } + return result(value, null); + } case this.tok.T_START_HEREDOC: - if (this.lexer.curCondition === 'ST_NOWDOC') { - var node = this.node('nowdoc'); - var value = this.next().text(); + if (this.lexer.curCondition === "ST_NOWDOC") { + const start = this.lexer.yylloc.first_offset; + node = this.node("nowdoc"); + value = this.next().text(); // strip the last line return char - var lastCh = value[value.length-1]; - if (lastCh === '\n') { - if (value[value.length-2] === '\r') { + if (this.lexer.heredoc_label.indentation > 0) { + value = value.substring( + 0, + value.length - this.lexer.heredoc_label.indentation, + ); + } + const lastCh = value[value.length - 1]; + if (lastCh === "\n") { + if (value[value.length - 2] === "\r") { // windows style value = value.substring(0, value.length - 2); } else { // linux style value = value.substring(0, value.length - 1); } - } else if (lastCh === '\r') { + } else if (lastCh === "\r") { // mac style value = value.substring(0, value.length - 1); } this.expect(this.tok.T_ENCAPSED_AND_WHITESPACE) && this.next(); - node = node(value, this.lexer.heredoc_label); this.expect(this.tok.T_END_HEREDOC) && this.next(); + const raw = this.lexer._input.substring( + start, + this.lexer.yylloc.first_offset, + ); + node = node( + this.remove_heredoc_leading_whitespace_chars( + value, + this.lexer.heredoc_label.indentation, + this.lexer.heredoc_label.indentation_uses_spaces, + this.lexer.heredoc_label.first_encaps_node, + ), + raw, + this.lexer.heredoc_label.label, + ); + this.lexer.heredoc_label.finished = true; return node; } else { - return this.next().read_encapsed_string( - this.tok.T_END_HEREDOC - ); + return this.read_encapsed_string(this.tok.T_END_HEREDOC); } case '"': - return this.next().read_encapsed_string('"'); + return this.read_encapsed_string('"'); case 'b"': - case 'B"': - var node = this.node('cast'); - var what = this.next().read_encapsed_string('"'); - return node('binary', what); - - // NUMERIC - case this.tok.T_LNUMBER: // long - case this.tok.T_DNUMBER: // double - var result = this.node('number'); - var value = this.text(); - this.next(); - result = result(value); - return result; + case 'B"': { + return this.read_encapsed_string('"', true); + } - // ARRAYS - case this.tok.T_ARRAY: // array parser - case '[': // short array format - return this.read_array(); - default: - var err = this.error('SCALAR'); + // TEXTS + case this.tok.T_CONSTANT_ENCAPSED_STRING: + case this.tok.T_ARRAY: // array parser + case "[": // short array format + return this.read_dereferencable_scalar(); + default: { + const err = this.error("SCALAR"); // graceful mode : ignore token & return error node this.next(); return err; + } } } - } - /** + }, + /* * Handles the dereferencing */ - ,read_dereferencable: function(expr) { - var result; - var node = this.node('offsetlookup'); - if (this.token === '[') { - var offset = this.next().read_expr(); - if (this.expect(']')) this.next(); + read_dereferencable: function (expr) { + let result, offset; + const node = this.node("offsetlookup"); + if (this.token === "[") { + offset = this.next().read_expr(); + if (this.expect("]")) this.next(); result = node(expr, offset); } else if (this.token === this.tok.T_DOLLAR_OPEN_CURLY_BRACES) { - var offset = this.read_encapsed_string_item(); + offset = this.read_encapsed_string_item(false); result = node(expr, offset); } return result; - } - /** + }, + /* * Reads and extracts an encapsed item * ```ebnf * encapsed_string_item ::= T_ENCAPSED_AND_WHITESPACE @@ -149,93 +322,120 @@ module.exports = { * @return {String|Variable|Expr|Lookup} * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1219 */ - ,read_encapsed_string_item: function() { - var result = this.node(); + read_encapsed_string_item: function (isDoubleQuote) { + const encapsedPart = this.node("encapsedpart"); + let syntax = null; + let curly = false; + let result = this.node(), + offset, + node, + name; // plain text // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1222 if (this.token === this.tok.T_ENCAPSED_AND_WHITESPACE) { - var text = this.text(); + const text = this.text(); this.next(); + + // if this.lexer.heredoc_label.first_encaps_node -> remove first indents result = result( - 'string', false, this.resolve_special_chars(text) + "string", + false, + this.version >= 703 && !this.lexer.heredoc_label.finished + ? this.remove_heredoc_leading_whitespace_chars( + this.resolve_special_chars(text, isDoubleQuote), + this.lexer.heredoc_label.indentation, + this.lexer.heredoc_label.indentation_uses_spaces, + this.lexer.heredoc_label.first_encaps_node, + ) + : text, + false, + text, ); - } - - // dynamic variable name - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1239 - else if (this.token === this.tok.T_DOLLAR_OPEN_CURLY_BRACES) { - var name = null; + } else if (this.token === this.tok.T_DOLLAR_OPEN_CURLY_BRACES) { + syntax = "simple"; + curly = true; + // dynamic variable name + // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1239 + name = null; if (this.next().token === this.tok.T_STRING_VARNAME) { - var varName = this.text(); - name = this.node('variable'); + name = this.node("variable"); + const varName = this.text(); this.next(); // check if lookup an offset // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1243 - if (this.token === '[') { + result.destroy(); + if (this.token === "[") { name = name(varName, false); - var node = this.node('offsetlookup'); - var offset = this.next().read_expr(); - this.expect(']') && this.next(); - name = node(name, offset); + node = this.node("offsetlookup"); + offset = this.next().read_expr(); + this.expect("]") && this.next(); + result = node(name, offset); } else { - name = varName; + result = name(varName, false); } } else { - name = this.read_expr(); + result = result("variable", this.read_expr(), false); } - this.expect('}') && this.next(); - result = result('variable', name, false, true); - } - - // expression - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1246 - else if (this.token === this.tok.T_CURLY_OPEN) { - result = this.next().read_variable(false, false, false); - this.expect('}') && this.next(); - } - - // plain variable - // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1231 - else if (this.token === this.tok.T_VARIABLE) { - result = this.read_simple_variable(false); + this.expect("}") && this.next(); + } else if (this.token === this.tok.T_CURLY_OPEN) { + // expression + // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1246 + syntax = "complex"; + result.destroy(); + result = this.next().read_variable(false, false); + this.expect("}") && this.next(); + } else if (this.token === this.tok.T_VARIABLE) { + syntax = "simple"; + // plain variable + // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1231 + result.destroy(); + result = this.read_simple_variable(); // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1233 - if (this.token === '[') { - var node = this.node('offsetlookup'); - var offset = this.next().read_encaps_var_offset(); - this.expect(']') && this.next(); + if (this.token === "[") { + node = this.node("offsetlookup"); + offset = this.next().read_encaps_var_offset(); + this.expect("]") && this.next(); result = node(result, offset); } // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L1236 if (this.token === this.tok.T_OBJECT_OPERATOR) { - var node = this.node('propertylookup'); - var what = this.node('constref'); + node = this.node("propertylookup"); this.next().expect(this.tok.T_STRING); - var name = this.text(); + const what = this.node("identifier"); + name = this.text(); this.next(); result = node(result, what(name)); } - // error / fallback + // error / fallback } else { this.expect(this.tok.T_ENCAPSED_AND_WHITESPACE); - var value = this.text(); + const value = this.text(); this.next(); // consider it as string - result = result('string', false, value); + result.destroy(); + result = result("string", false, value, false, value); } - return result; - } - /** + // reset first_encaps_node to false after access any node + this.lexer.heredoc_label.first_encaps_node = false; + return encapsedPart(result, syntax, curly); + }, + /* * Reads an encapsed string */ - ,read_encapsed_string: function(expect) { - var node = this.node('encapsed'), value = [], type = null; + read_encapsed_string: function (expect, isBinary = false) { + const labelStart = this.lexer.yylloc.first_offset; + let node = this.node("encapsed"); + this.next(); + const start = this.lexer.yylloc.prev_offset - (isBinary ? 1 : 0); + const value = []; + let type = null; - if (expect === '`') { + if (expect === "`") { type = this.ast.encapsed.TYPE_SHELL; } else if (expect === '"') { type = this.ast.encapsed.TYPE_STRING; @@ -244,25 +444,49 @@ module.exports = { } // reading encapsed parts - while(this.token !== expect && this.token !== this.EOF) { - value.push(this.read_encapsed_string_item()); + while (this.token !== expect && this.token !== this.EOF) { + value.push(this.read_encapsed_string_item(true)); + } + if ( + value.length > 0 && + value[value.length - 1].kind === "encapsedpart" && + value[value.length - 1].expression.kind === "string" + ) { + const node = value[value.length - 1].expression; + const lastCh = node.value[node.value.length - 1]; + if (lastCh === "\n") { + if (node.value[node.value.length - 2] === "\r") { + // windows style + node.value = node.value.substring(0, node.value.length - 2); + } else { + // linux style + node.value = node.value.substring(0, node.value.length - 1); + } + } else if (lastCh === "\r") { + // mac style + node.value = node.value.substring(0, node.value.length - 1); + } } - this.expect(expect) && this.next(); - node = node(value, type); + const raw = this.lexer._input.substring( + type === "heredoc" ? labelStart : start - 1, + this.lexer.yylloc.first_offset, + ); + node = node(value, raw, type); if (expect === this.tok.T_END_HEREDOC) { - node.label = this.lexer.heredoc_label; + node.label = this.lexer.heredoc_label.label; + this.lexer.heredoc_label.finished = true; } return node; - } - /** + }, + /* * Constant token */ - ,get_magic_constant: function() { - var result = this.node('magic'); - var name = this.text(); + get_magic_constant: function () { + const result = this.node("magic"); + const name = this.text(); this.next(); - return result(name); - } + return result(name.toUpperCase(), name); + }, }; diff --git a/src/parser/statement.js b/src/parser/statement.js index a9ceaa8fb..09b8f7ddf 100644 --- a/src/parser/statement.js +++ b/src/parser/statement.js @@ -1,19 +1,21 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; + module.exports = { - /** + /* * reading a list of top statements (helper for top_statement*) * ```ebnf * top_statements ::= top_statement* * ``` */ - read_top_statements: function() { - var result = []; - while(this.token !== this.EOF && this.token !== '}') { - var statement = this.read_top_statement(); + read_top_statements: function () { + let result = []; + while (this.token !== this.EOF && this.token !== "}") { + const statement = this.read_top_statement(); if (statement) { if (Array.isArray(statement)) { result = result.concat(statement); @@ -23,8 +25,8 @@ module.exports = { } } return result; - } - /** + }, + /* * reading a top statement * ```ebnf * top_statement ::= @@ -34,56 +36,58 @@ module.exports = { * | statement * ``` */ - ,read_top_statement: function() { - switch(this.token) { + read_top_statement: function () { + let attrs = []; + if (this.token === this.tok.T_ATTRIBUTE) { + attrs = this.read_attr_list(); + } + switch (this.token) { case this.tok.T_FUNCTION: - return this.read_function(false, false); + return this.read_function(false, false, attrs); // optional flags case this.tok.T_ABSTRACT: case this.tok.T_FINAL: - var flag = this.read_class_scope(); - if (this.token === this.tok.T_CLASS) { - return this.read_class(flag); - } else { - this.error(this.tok.T_CLASS); - this.next(); - return null; - } + case this.tok.T_READ_ONLY: case this.tok.T_CLASS: - return this.read_class([0, 0, 0]); + return this.read_class_declaration_statement(attrs); case this.tok.T_INTERFACE: - return this.read_interface(); + return this.read_interface_declaration_statement(attrs); case this.tok.T_TRAIT: - return this.read_trait(); + return this.read_trait_declaration_statement(); + case this.tok.T_ENUM: + return this.read_enum_declaration_statement(attrs); case this.tok.T_USE: return this.read_use_statement(); - case this.tok.T_CONST: - return this.next().read_const_list(); + case this.tok.T_CONST: { + const result = this.node("constantstatement"); + const items = this.next().read_const_list(); + this.expectEndOfStatement(); + return result(null, items); + } case this.tok.T_NAMESPACE: return this.read_namespace(); - case this.tok.T_HALT_COMPILER: - var result = this.node('halt'); - if (this.next().expect('(')) this.next(); - if (this.expect(')')) this.next(); - this.expect(';'); + case this.tok.T_HALT_COMPILER: { + const result = this.node("halt"); + if (this.next().expect("(")) this.next(); + if (this.expect(")")) this.next(); + this.expect(";"); this.lexer.done = true; - return result(this.lexer._input.substring( - this.lexer.offset - )); + return result(this.lexer._input.substring(this.lexer.offset)); + } default: return this.read_statement(); } - } - /** + }, + /* * reads a list of simple inner statements (helper for inner_statement*) * ```ebnf * inner_statements ::= inner_statement* * ``` */ - ,read_inner_statements: function() { - var result = []; - while(this.token != this.EOF && this.token !== '}') { - var statement = this.read_inner_statement(); + read_inner_statements: function () { + let result = []; + while (this.token != this.EOF && this.token !== "}") { + const statement = this.read_inner_statement(); if (statement) { if (Array.isArray(statement)) { result = result.concat(statement); @@ -93,275 +97,348 @@ module.exports = { } } return result; - } - /** + }, + /* * Reads a list of constants declaration * ```ebnf * const_list ::= T_CONST T_STRING '=' expr (',' T_STRING '=' expr)* ';' * ``` */ - ,read_const_list: function() { - var result = this.read_list(function() { - this.expect(this.tok.T_STRING); - var result = this.node('constant'); - var name = this.text(); - if (this.next().expect('=')) { - return result(name, this.next().read_expr()); - } else { - // fallback - return result(name, null); - } - }, ',', false); - this.expectEndOfStatement(); - return result; - } - /** + read_const_list: function () { + return this.read_list( + function () { + this.expect(this.tok.T_STRING); + const result = this.node("constant"); + let constName = this.node("identifier"); + const name = this.text(); + this.next(); + constName = constName(name); + if (this.expect("=")) { + return result(constName, this.next().read_expr()); + } else { + // fallback + return result(constName, null); + } + }, + ",", + false, + ); + }, + /* * Reads a list of constants declaration * ```ebnf - * declare_list ::= T_STRING '=' expr (',' T_STRING '=' expr)* + * declare_list ::= IDENTIFIER '=' expr (',' IDENTIFIER '=' expr)* * ``` - * @retrurn {Object} + * @retrurn {Array} */ - ,read_declare_list: function() { - var result = {}; - while(this.token != this.EOF && this.token !== ')') { + read_declare_list: function () { + const result = []; + while (this.token != this.EOF && this.token !== ")") { this.expect(this.tok.T_STRING); - var name = this.text().toLowerCase(); - if (this.next().expect('=')) { - result[name] = this.next().read_expr(); - } else { - result[name] = null; + const directive = this.node("declaredirective"); + let key = this.node("identifier"); + const name = this.text(); + this.next(); + key = key(name); + let value = null; + if (this.expect("=")) { + value = this.next().read_expr(); } - if (this.token !== ',') break; + result.push(directive(key, value)); + if (this.token !== ",") break; this.next(); } return result; - } - /** + }, + /* * reads a simple inner statement * ```ebnf * inner_statement ::= '{' inner_statements '}' | token * ``` */ - ,read_inner_statement: function() { - switch(this.token) { - case this.tok.T_FUNCTION: - return this.read_function(false, false); + read_inner_statement: function () { + let attrs = []; + if (this.token === this.tok.T_ATTRIBUTE) { + attrs = this.read_attr_list(); + } + switch (this.token) { + case this.tok.T_FUNCTION: { + const result = this.read_function(false, false); + result.attrGroups = attrs; + return result; + } // optional flags case this.tok.T_ABSTRACT: case this.tok.T_FINAL: - var flag = this.read_class_scope(); - if (this.token === this.tok.T_CLASS) { - return this.read_class(flag); - } else { - this.error(this.tok.T_CLASS); - // graceful mode : ignore token & go next - this.next(); - return null; - } case this.tok.T_CLASS: - return this.read_class([0, 0, 0]); + return this.read_class_declaration_statement(); case this.tok.T_INTERFACE: - return this.read_interface(); + return this.read_interface_declaration_statement(); case this.tok.T_TRAIT: - return this.read_trait(); - case this.tok.T_HALT_COMPILER: + return this.read_trait_declaration_statement(); + case this.tok.T_ENUM: + return this.read_enum_declaration_statement(); + case this.tok.T_HALT_COMPILER: { this.raiseError( - '__HALT_COMPILER() can only be used from the outermost scope' + "__HALT_COMPILER() can only be used from the outermost scope", ); // fallback : returns a node but does not stop the parsing - var node = this.node('halt'); - this.next().expect('(') && this.next(); - this.expect(')') && this.next(); - node = node(this.lexer._input.substring( - this.lexer.offset - )); - this.expect(';') && this.next(); + let node = this.node("halt"); + this.next().expect("(") && this.next(); + this.expect(")") && this.next(); + node = node(this.lexer._input.substring(this.lexer.offset)); + this.expect(";") && this.next(); return node; + } default: return this.read_statement(); } - } - /** + }, + /* * Reads statements */ - ,read_statement: function() { - - switch(this.token) { + read_statement: function () { + switch (this.token) { + case "{": + return this.read_code_block(false); - case '{': return this.read_code_block(false); + case this.tok.T_IF: + return this.read_if(); - case this.tok.T_IF: return this.next().read_if(); + case this.tok.T_SWITCH: + return this.read_switch(); - case this.tok.T_SWITCH: return this.read_switch(); + case this.tok.T_FOR: + return this.read_for(); - case this.tok.T_FOR: return this.next().read_for(); + case this.tok.T_FOREACH: + return this.read_foreach(); - case this.tok.T_FOREACH: return this.next().read_foreach(); + case this.tok.T_WHILE: + return this.read_while(); - case this.tok.T_WHILE: return this.next().read_while(); + case this.tok.T_DO: + return this.read_do(); - case this.tok.T_DO: return this.next().read_do(); + case this.tok.T_COMMENT: + return this.read_comment(); - case this.tok.T_COMMENT: return this.read_comment(); + case this.tok.T_DOC_COMMENT: + return this.read_doc_comment(); - case this.tok.T_DOC_COMMENT: return this.read_doc_comment(); - - case this.tok.T_RETURN: - var result = this.node('return'), expr = null; - if (!this.next().is('EOS')) { - expr = this.read_expr(); - } + case this.tok.T_RETURN: { + const result = this.node("return"); + this.next(); + const expr = this.read_optional_expr(";"); this.expectEndOfStatement(); return result(expr); + } // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L429 case this.tok.T_BREAK: - case this.tok.T_CONTINUE: - var result = this.node( - this.token === this.tok.T_CONTINUE ? 'continue' : 'break' - ), level = null; - this.next(); // look ahead - if (this.token !== ';' && this.token !== this.tok.T_CLOSE_TAG) { - level = this.read_expr(); - } + case this.tok.T_CONTINUE: { + const result = this.node( + this.token === this.tok.T_CONTINUE ? "continue" : "break", + ); + this.next(); + const level = this.read_optional_expr(";"); this.expectEndOfStatement(); return result(level); + } - case this.tok.T_GLOBAL: - var result = this.node('global'); - var items = this.next().read_list(this.read_simple_variable, ','); + case this.tok.T_GLOBAL: { + const result = this.node("global"); + const items = this.next().read_list(this.read_simple_variable, ","); this.expectEndOfStatement(); return result(items); + } - case this.tok.T_STATIC: - var current = [this.token, this.lexer.getState()]; - var result = this.node('static'); + case this.tok.T_STATIC: { + const current = [this.token, this.lexer.getState()]; + const result = this.node(); if (this.next().token === this.tok.T_DOUBLE_COLON) { // static keyword for a class this.lexer.tokens.push(current); - var expr = this.next().read_expr(); - this.expect(';') && this.nextWithComments(); - return expr; + const expr = this.next().read_expr(); + this.expectEndOfStatement(expr); + return result("expressionstatement", expr); } if (this.token === this.tok.T_FUNCTION) { return this.read_function(true, [0, 1, 0]); } - var items = this.read_variable_declarations(); + const items = this.read_variable_declarations(); this.expectEndOfStatement(); - return result(items); + return result("static", items); + } - case this.tok.T_ECHO: - var result = this.node('echo'); - var args = this.next().read_list(this.read_expr, ','); + case this.tok.T_ECHO: { + const result = this.node("echo"); + const text = this.text(); + const shortForm = text === " 0 + ? this.lexer._input[this.lexer.yylloc.first_offset - 1] + : null; + const fixFirstLine = prevChar === "\r" || prevChar === "\n"; + // revert back the first stripped line + if (fixFirstLine) { + if ( + prevChar === "\n" && + this.lexer.yylloc.first_offset > 1 && + this.lexer._input[this.lexer.yylloc.first_offset - 2] === "\r" + ) { + prevChar = "\r\n"; + } + } + const result = this.node("inline"); this.next(); - return result(value); + return result(value, fixFirstLine ? prevChar + value : value); + } - case this.tok.T_UNSET: - var result = this.node('unset'); - this.next().expect('(') && this.next(); - var items = this.read_list(this.read_variable, ','); - this.expect(')') && this.next(); - this.expect(';') && this.nextWithComments(); - return result(items); + case this.tok.T_UNSET: { + const result = this.node("unset"); + this.next().expect("(") && this.next(); + const variables = this.read_function_list(this.read_variable, ","); + this.expect(")") && this.next(); + this.expect(";") && this.next(); + return result(variables); + } - case this.tok.T_DECLARE: - var result = this.node('declare'), - what, - body = [], - mode; - this.next().expect('(') && this.next(); - what = this.read_declare_list(); - this.expect(')') && this.next(); - if (this.token === ':') { - this.nextWithComments(); - while(this.token != this.EOF && this.token !== this.tok.T_ENDDECLARE) { + case this.tok.T_DECLARE: { + const result = this.node("declare"); + const body = []; + let mode; + this.next().expect("(") && this.next(); + const directives = this.read_declare_list(); + this.expect(")") && this.next(); + if (this.token === ":") { + this.next(); + while ( + this.token != this.EOF && + this.token !== this.tok.T_ENDDECLARE + ) { // @todo : check declare_statement from php / not valid body.push(this.read_top_statement()); } + if ( + body.length === 0 && + this.extractDoc && + this._docs.length > this._docIndex + ) { + body.push(this.node("noop")()); + } this.expect(this.tok.T_ENDDECLARE) && this.next(); this.expectEndOfStatement(); mode = this.ast.declare.MODE_SHORT; - } else if (this.token === '{') { - this.nextWithComments(); - while(this.token != this.EOF && this.token !== '}') { + } else if (this.token === "{") { + this.next(); + while (this.token != this.EOF && this.token !== "}") { // @todo : check declare_statement from php / not valid body.push(this.read_top_statement()); } - this.expect('}') && this.next(); + if ( + body.length === 0 && + this.extractDoc && + this._docs.length > this._docIndex + ) { + body.push(this.node("noop")()); + } + this.expect("}") && this.next(); mode = this.ast.declare.MODE_BLOCK; } else { - this.expect(';') && this.nextWithComments(); - while(this.token != this.EOF && this.token !== this.tok.T_DECLARE) { - // @todo : check declare_statement from php / not valid - body.push(this.read_top_statement()); - } + this.expect(";") && this.next(); mode = this.ast.declare.MODE_NONE; } - return result(what, body, mode); + return result(directives, body, mode); + } case this.tok.T_TRY: return this.read_try(); - case this.tok.T_THROW: - var result = this.node('throw'); - var expr = this.next().read_expr(); + case this.tok.T_THROW: { + const result = this.node("throw"); + const expr = this.next().read_expr(); this.expectEndOfStatement(); return result(expr); + } - case ';': // ignore this (extra ponctuation) - case this.tok.T_CLOSE_TAG: // empty tag + // ignore this (extra ponctuation) + case ";": { this.next(); return null; + } - case this.tok.T_STRING: - var current = [this.token, this.lexer.getState()]; - var label = this.text(); + case this.tok.T_STRING: { + const result = this.node(); + const current = [this.token, this.lexer.getState()]; + const labelNameText = this.text(); + let labelName = this.node("identifier"); // AST : https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L457 - if (this.next().token === ':') { - var result = this.node('label'); + if (this.next().token === ":") { + labelName = labelName(labelNameText); this.next(); - return result(label); + return result("label", labelName); + } else { + labelName.destroy(); } // default fallback expr / T_STRING '::' (etc...) + result.destroy(); this.lexer.tokens.push(current); - var expr = this.next().read_expr(); - this.expectEndOfStatement(); - return expr; + const statement = this.node("expressionstatement"); + const expr = this.next().read_expr(); + this.expectEndOfStatement(expr); + return statement(expr); + } - case this.tok.T_GOTO: - var result = this.node('goto'), label = null; + case this.tok.T_GOTO: { + const result = this.node("goto"); + let labelName = null; if (this.next().expect(this.tok.T_STRING)) { - label = this.text(); - this.next().expectEndOfStatement(); + labelName = this.node("identifier"); + const name = this.text(); + this.next(); + labelName = labelName(name); + this.expectEndOfStatement(); } - return result(label); + return result(labelName); + } - default: // default fallback expr - var expr = this.read_expr(); - this.expectEndOfStatement(); - return expr; + default: { + // default fallback expr + const statement = this.node("expressionstatement"); + const expr = this.read_expr(); + this.expectEndOfStatement(expr); + return statement(expr); + } } - } - /** + }, + /* * ```ebnf * code_block ::= '{' (inner_statements | top_statements) '}' * ``` */ - ,read_code_block: function(top) { - var result = this.node('block'); - this.expect('{') && this.nextWithComments(); - var body = top ? - this.read_top_statements() - : this.read_inner_statements() - ; - this.expect('}') && this.nextWithComments(); + read_code_block: function (top) { + const result = this.node("block"); + this.expect("{") && this.next(); + const body = top + ? this.read_top_statements() + : this.read_inner_statements(); + if ( + body.length === 0 && + this.extractDoc && + this._docs.length > this._docIndex + ) { + body.push(this.node("noop")()); + } + this.expect("}") && this.next(); return result(null, body); - } + }, }; diff --git a/src/parser/switch.js b/src/parser/switch.js index afe98c905..07c1785e7 100644 --- a/src/parser/switch.js +++ b/src/parser/switch.js @@ -1,12 +1,12 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; module.exports = { - /** + /* * Reads a switch statement * ```ebnf * switch ::= T_SWITCH '(' expr ')' switch_case_list @@ -14,46 +14,50 @@ module.exports = { * @return {Switch} * @see http://php.net/manual/en/control-structures.switch.php */ - read_switch: function() { + read_switch: function () { + const result = this.node("switch"); this.expect(this.tok.T_SWITCH) && this.next(); - var result = this.node('switch'), test, body, shortForm; - this.expect('(') && this.next(); - test = this.read_expr(); - this.expect(')') && this.next(); - shortForm = (this.token === ':'); - body = this.read_switch_case_list(); + this.expect("(") && this.next(); + const test = this.read_expr(); + this.expect(")") && this.next(); + const shortForm = this.token === ":"; + const body = this.read_switch_case_list(); return result(test, body, shortForm); - } - /** + }, + /* * ```ebnf * switch_case_list ::= '{' ';'? case_list* '}' | ':' ';'? case_list* T_ENDSWITCH ';' * ``` * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L566 */ - ,read_switch_case_list: function() { + read_switch_case_list: function () { // DETECT SWITCH MODE - var expect = null, - result = this.node('block'), - items = []; - if (this.token === '{') { - expect = '}'; - } else if (this.token === ':') { + let expect = null; + const result = this.node("block"); + const items = []; + if (this.token === "{") { + expect = "}"; + } else if (this.token === ":") { expect = this.tok.T_ENDSWITCH; } else { - this.expect(['{', ':']); + this.expect(["{", ":"]); } + this.next(); // OPTIONNAL ';' // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L570 - if (this.next().token === ';') { - this.next(); - } - // IGNORE THE CLOSE TAG TOKEN WITH SHORT MODE - if (this.token === this.tok.T_CLOSE_TAG) { + if (this.token === ";") { this.next(); } // EXTRACTING CASES - while(this.token !== this.EOF && this.token !== expect) { - items.push( this.read_case_list(expect) ); + while (this.token !== this.EOF && this.token !== expect) { + items.push(this.read_case_list(expect)); + } + if ( + items.length === 0 && + this.extractDoc && + this._docs.length > this._docIndex + ) { + items.push(this.node("noop")()); } // CHECK END TOKEN this.expect(expect) && this.next(); @@ -61,34 +65,35 @@ module.exports = { this.expectEndOfStatement(); } return result(null, items); - } - /** + }, + /* * ```ebnf * case_list ::= ((T_CASE expr) | T_DEFAULT) (':' | ';') inner_statement* * ``` */ - ,read_case_list: function(stopToken) { - var result = this.node('case'), test = null, body = null, items = []; + read_case_list: function (stopToken) { + const result = this.node("case"); + let test = null; if (this.token === this.tok.T_CASE) { test = this.next().read_expr(); } else if (this.token === this.tok.T_DEFAULT) { - // the defaut entry - no condition + // the default entry - no condition this.next(); } else { this.expect([this.tok.T_CASE, this.tok.T_DEFAULT]); } - this.expect([':', ';']) && this.next(); - body = this.node('block'); - while( - this.token != this.EOF - && this.token !== stopToken - && this.token !== this.tok.T_CASE - && this.token !== this.tok.T_DEFAULT + // case_separator + this.expect([":", ";"]) && this.next(); + const body = this.node("block"); + const items = []; + while ( + this.token !== this.EOF && + this.token !== stopToken && + this.token !== this.tok.T_CASE && + this.token !== this.tok.T_DEFAULT ) { items.push(this.read_inner_statement()); } - return result( - test, items.length > 0 ? body(null, items) : null - ); - } + return result(test, body(null, items)); + }, }; diff --git a/src/parser/try.js b/src/parser/try.js index 02dcb164a..60c396116 100644 --- a/src/parser/try.js +++ b/src/parser/try.js @@ -1,44 +1,43 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; + module.exports = { - /** + /* * ```ebnf * try ::= T_TRY '{' inner_statement* '}' * ( - * T_CATCH '(' namespace_name variable ')' '{' inner_statement* '}' + * T_CATCH '(' namespace_name (variable)? ')' '{' inner_statement* '}' * )* * (T_FINALLY '{' inner_statement* '}')? * ``` * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L448 * @return {Try} */ - read_try: function() { + read_try: function () { this.expect(this.tok.T_TRY); - var result = this.node('try'), - always = null, - body, - catches = [] - ; - body = this.next().read_statement(); + const result = this.node("try"); + let always = null; + const catches = []; + const body = this.next().read_statement(); // https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L455 - while(this.ignoreComments().token === this.tok.T_CATCH) { - var item = this.node('catch'), what = [], variable = null; - this.next().expect('(') && this.next(); - what = this.read_list( - this.read_namespace_name, '|', false - ); - variable = this.read_variable(true, false, false); - this.expect(')'); - catches.push( - item(this.next().read_statement(), what, variable) - ); + while (this.token === this.tok.T_CATCH) { + const item = this.node("catch"); + this.next().expect("(") && this.next(); + const what = this.read_list(this.read_namespace_name, "|", false); + let variable = null; + if (this.version < 800 || this.token === this.tok.T_VARIABLE) { + variable = this.read_variable(true, false); + } + this.expect(")"); + catches.push(item(this.next().read_statement(), what, variable)); } if (this.token === this.tok.T_FINALLY) { always = this.next().read_statement(); } return result(body, catches, always); - } + }, }; diff --git a/src/parser/utils.js b/src/parser/utils.js index 0664c06f5..73734fc54 100644 --- a/src/parser/utils.js +++ b/src/parser/utils.js @@ -1,49 +1,86 @@ -/*! - * Defines a list of helper functions for parsing - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ "use strict"; module.exports = { - /** + /* * Reads a short form of tokens * @param {Number} token - The ending token * @return {Block} */ - read_short_form: function(token) { - var body = this.node('block'), items = []; - if (this.expect(':')) this.next(); - while(this.token != this.EOF && this.token !== token) { + read_short_form: function (token) { + const body = this.node("block"); + const items = []; + /* istanbul ignore next */ + if (this.expect(":")) this.next(); + while (this.token != this.EOF && this.token !== token) { items.push(this.read_inner_statement()); } + if ( + items.length === 0 && + this.extractDoc && + this._docs.length > this._docIndex + ) { + items.push(this.node("noop")()); + } + /* istanbul ignore next */ if (this.expect(token)) this.next(); this.expectEndOfStatement(); return body(null, items); - } + }, + + /* + * https://wiki.php.net/rfc/trailing-comma-function-calls + * @param {*} item + * @param {*} separator + */ + read_function_list: function (item, separator) { + const result = []; + do { + if (this.token == separator && this.version >= 703 && result.length > 0) { + result.push(this.node("noop")()); + break; + } + result.push(item.apply(this, [])); + if (this.token != separator) { + break; + } + if (this.next().token == ")" && this.version >= 703) { + break; + } + } while (this.token != this.EOF); + return result; + }, - /** + /* * Helper : reads a list of tokens / sample : T_STRING ',' T_STRING ... * ```ebnf * list ::= separator? ( item separator )* item * ``` */ - ,read_list: function(item, separator, preserveFirstSeparator) { - var result = []; + read_list: function (item, separator, preserveFirstSeparator) { + const result = []; if (this.token == separator) { - if (preserveFirstSeparator) result.push(''); + if (preserveFirstSeparator) { + result.push(typeof item === "function" ? this.node("noop")() : null); + } this.next(); } - if (typeof (item) === "function") { + if (typeof item === "function") { do { - result.push(item.apply(this, [])); + const itemResult = item.apply(this, []); + if (itemResult) { + result.push(itemResult); + } if (this.token != separator) { break; } - } while(this.next().token != this.EOF); + } while (this.next().token != this.EOF); } else { if (this.expect(item)) { result.push(this.text()); @@ -58,9 +95,9 @@ module.exports = { } } return result; - } + }, - /** + /* * Reads a list of names separated by a comma * * ```ebnf @@ -73,15 +110,29 @@ module.exports = { * ``` * * @see https://github.com/php/php-src/blob/master/Zend/zend_language_parser.y#L726 - * @return {Identifier[]} + * @return {Reference[]} + */ + read_name_list: function () { + return this.read_list(this.read_namespace_name, ",", false); + }, + + /* + * Reads the byref token and assign it to the specified node + * @param {*} cb */ - ,read_name_list: function() { - return this.read_list( - this.read_namespace_name, ',', false - ); - } + read_byref: function (cb) { + let byref = this.node("byref"); + this.next(); + byref = byref(null); + const result = cb(); + if (result) { + this.ast.swapLocations(result, byref, result, this); + result.byref = true; + } + return result; + }, - /** + /* * Reads a list of variables declarations * * ```ebnf @@ -91,30 +142,62 @@ module.exports = { * * Sample code : * ```php - * func()->property // chained calls * ``` */ - read_variable: function(read_only, encapsed, byref) { - var result; - + read_variable: function (read_only, encapsed) { + let result; // check the byref flag - if (!byref && this.token === '&') { - byref = true; - this.next(); + if (this.token === "&") { + return this.read_byref( + this.read_variable.bind(this, read_only, encapsed), + ); } // reads the entry point - if (this.is([this.tok.T_VARIABLE, '$'])) { - result = this.read_reference_variable(encapsed, byref); - } else if (this.is([this.tok.T_NS_SEPARATOR, this.tok.T_STRING, this.tok.T_NAMESPACE])) { + if (this.is([this.tok.T_VARIABLE, "$"])) { + result = this.read_reference_variable(encapsed); + } else if ( + this.is([ + this.tok.T_NS_SEPARATOR, + this.tok.T_STRING, + this.tok.T_NAME_RELATIVE, + this.tok.T_NAME_QUALIFIED, + this.tok.T_NAME_FULLY_QUALIFIED, + this.tok.T_NAMESPACE, + ]) + ) { result = this.node(); - var name = this.read_namespace_name(); + const name = this.read_namespace_name(); if ( - this.token != this.tok.T_DOUBLE_COLON - && this.token != '(' + this.token != this.tok.T_DOUBLE_COLON && + this.token != "(" && + ["parentreference", "selfreference"].indexOf(name.kind) === -1 ) { // @see parser.js line 130 : resolves a conflict with scalar - var literal = name.name.toLowerCase(); - if (literal === 'true') { - result = result('boolean', true); - } else if (literal === 'false') { - result = result('boolean', false); + const literal = name.name.toLowerCase(); + if (literal === "true") { + result = name.destroy(result("boolean", true, name.name)); + } else if (literal === "false") { + result = name.destroy(result("boolean", false, name.name)); + } else if (literal === "null") { + result = name.destroy(result("nullkeyword", name.name)); } else { - // @todo null keyword ? - result = result('constref', name); + result.destroy(name); + result = name; } } else { + // @fixme possible #193 bug + result.destroy(name); result = name; } } else if (this.token === this.tok.T_STATIC) { - result = this.node('constref'); + result = this.node("staticreference"); + const raw = this.text(); this.next(); - result = result('static'); + result = result(raw); } else { - this.expect('VARIABLE'); + this.expect("VARIABLE"); } // static mode @@ -67,170 +83,201 @@ module.exports = { } return this.recursive_variable_chain_scan(result, read_only, encapsed); - } + }, // resolves a static call - ,read_static_getter: function(what, encapsed) { - var result = this.node('staticlookup'); - var offset = null; - if (this.next().is([this.tok.T_VARIABLE, '$'])) { - offset = this.read_reference_variable(encapsed, false); + read_static_getter: function (what, encapsed) { + const result = this.node("staticlookup"); + let offset, name; + if (this.next().is([this.tok.T_VARIABLE, "$"])) { + offset = this.read_reference_variable(encapsed); } else if ( - this.token === this.tok.T_STRING - || this.token === this.tok.T_CLASS + this.token === this.tok.T_STRING || + this.token === this.tok.T_CLASS || + (this.version >= 700 && this.is("IDENTIFIER")) ) { - offset = this.node('constref'); - var name = this.text(); + offset = this.node("identifier"); + name = this.text(); this.next(); offset = offset(name); + } else if (this.token === "{") { + offset = this.node("literal"); + name = this.next().read_expr(); + this.expect("}") && this.next(); + offset = offset("literal", name, null); + this.expect("("); } else { this.error([this.tok.T_VARIABLE, this.tok.T_STRING]); // graceful mode : set getter as error node and continue - offset = this.node('constref'); - var name = this.text(); + offset = this.node("identifier"); + name = this.text(); this.next(); offset = offset(name); } return result(what, offset); - } + }, - ,recursive_variable_chain_scan: function(result, read_only, encapsed) { - recursive_scan_loop: - while(this.token != this.EOF) { - switch(this.token) { - case '(': + read_what: function (is_static_lookup = false) { + let what = null; + let name = null; + switch (this.next().token) { + case this.tok.T_STRING: + what = this.node("identifier"); + name = this.text(); + this.next(); + what = what(name); + + if (is_static_lookup && this.token === this.tok.T_OBJECT_OPERATOR) { + this.error(); + } + break; + case this.tok.T_VARIABLE: + what = this.node("variable"); + name = this.text().substring(1); + this.next(); + what = what(name, false); + break; + case "$": + what = this.node(); + this.next().expect(["$", "{", this.tok.T_VARIABLE]); + if (this.token === "{") { + // $obj->${$varname} + name = this.next().read_expr(); + this.expect("}") && this.next(); + what = what("variable", name, true); + } else { + // $obj->$$varname + name = this.read_expr(); + what = what("variable", name, false); + } + break; + case "{": + what = this.node("encapsedpart"); + name = this.next().read_expr(); + this.expect("}") && this.next(); + what = what(name, "complex", false); + break; + default: + this.error([this.tok.T_STRING, this.tok.T_VARIABLE, "$", "{"]); + // graceful mode : set what as error mode & continue + what = this.node("identifier"); + name = this.text(); + this.next(); + what = what(name); + break; + } + + return what; + }, + + recursive_variable_chain_scan: function (result, read_only, encapsed) { + let node, offset; + recursive_scan_loop: while (this.token != this.EOF) { + switch (this.token) { + case "(": if (read_only) { // @fixme : add more informations & test return result; } else { - result = this.node('call')( - result, this.read_function_argument_list() - ); + result = this.node("call")(result, this.read_argument_list()); } break; - case '[': - var node = this.node('offsetlookup'); + case "[": + case "{": { + const backet = this.token; + const isSquareBracket = backet === "["; + node = this.node("offsetlookup"); this.next(); - var offset = false; + offset = false; if (encapsed) { offset = this.read_encaps_var_offset(); - this.expect(']') && this.next(); + this.expect(isSquareBracket ? "]" : "}") && this.next(); } else { + const isCallableVariable = isSquareBracket + ? this.token !== "]" + : this.token !== "}"; // callable_variable : https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L1122 - if (this.token !== ']') { + if (isCallableVariable) { offset = this.read_expr(); - this.expect(']') && this.next(); + this.expect(isSquareBracket ? "]" : "}") && this.next(); } else { this.next(); } } result = node(result, offset); break; - case this.tok.T_OBJECT_OPERATOR: - var node = this.node('propertylookup'); - var what = null; - switch(this.next().token) { - case this.tok.T_STRING: - what = this.node('constref'); - var name = this.text(); - this.next(); - what = what(name); - if (this.token === this.tok.T_VARIABLE) { - var inner = this.node('variable'); - name = this.text().substring(1); - this.next(); - what = this.node('encapsed')( - [what, inner(name, false, false)], - 'offset' - ); - if (what.loc && what.value[0].loc) { - what.loc.start = what.value[0].loc.start; - } - } else if (this.token === '{') { - var expr = this.next().read_expr(); - this.expect('}') && this.next(); - what = this.node('encapsed')( - [what, expr], - 'offset' - ); - if (what.loc && what.value[0].loc) { - what.loc.start = what.value[0].loc.start; - } - } - break; - case this.tok.T_VARIABLE: - what = this.node('variable'); - var name = this.text().substring(1); - this.next(); - what = what(name, false, false); - break; - case '$': - this.next().expect(['{', this.tok.T_VARIABLE]); - if (this.token === '{') { - // $obj->${$varname} - what = this.next().read_expr(); - this.expect('}') && this.next(); - } else { - // $obj->$$varname - what = this.read_expr(); - } - break; - case '{': - what = this.next().read_expr(); - this.expect('}') && this.next(); - break; - default: - this.error([this.tok.T_STRING, this.tok.T_VARIABLE]); - // graceful mode : set what as error mode & continue - what = this.node('constref'); - var name = this.text(); - this.next(); - what = what(name); - break; + } + case this.tok.T_DOUBLE_COLON: + // @see https://github.com/glayzzle/php-parser/issues/107#issuecomment-354104574 + if ( + result.kind === "staticlookup" && + result.offset.kind === "identifier" + ) { + this.error(); } - result = node(result, what); + + node = this.node("staticlookup"); + result = node(result, this.read_what(true)); + + // fix 185 + // static lookup dereferencables are limited to staticlookup over functions + /*if (dereferencable && this.token !== "(") { + this.error("("); + }*/ + break; + case this.tok.T_OBJECT_OPERATOR: { + node = this.node("propertylookup"); + result = node(result, this.read_what()); break; + } + case this.tok.T_NULLSAFE_OBJECT_OPERATOR: { + node = this.node("nullsafepropertylookup"); + result = node(result, this.read_what()); + break; + } default: break recursive_scan_loop; } } return result; - } - /** + }, + /* * https://github.com/php/php-src/blob/493524454d66adde84e00d249d607ecd540de99f/Zend/zend_language_parser.y#L1231 */ - ,read_encaps_var_offset: function() { - var offset = this.node(); + read_encaps_var_offset: function () { + let offset = this.node(); if (this.token === this.tok.T_STRING) { - var text = this.text(); - var isDblQuote = text[0] === '"'; - text = text.substring(1, text.length - 1); + const text = this.text(); this.next(); - offset = offset( - 'string', isDblQuote, this.resolve_special_chars(text) - ); + offset = offset("identifier", text); } else if (this.token === this.tok.T_NUM_STRING) { - var num = this.text(); + const num = this.text(); this.next(); - offset = offset('number', num); + offset = offset("number", num, null); + } else if (this.token === "-") { + this.next(); + const num = -1 * this.text(); + this.expect(this.tok.T_NUM_STRING) && this.next(); + offset = offset("number", num, null); } else if (this.token === this.tok.T_VARIABLE) { - var name = this.text().substring(1); + const name = this.text().substring(1); this.next(); - offset = offset('variable', name, false, false); + offset = offset("variable", name, false); } else { this.expect([ this.tok.T_STRING, this.tok.T_NUM_STRING, - this.tok.T_VARIABLE + "-", + this.tok.T_VARIABLE, ]); - // fallback : consider as text - var text = this.text(); + // fallback : consider as identifier + const text = this.text(); this.next(); - offset = offset('string', false, text); + offset = offset("identifier", text); } return offset; - } - /** + }, + /* * ```ebnf * reference_variable ::= simple_variable ('[' OFFSET ']')* | '{' EXPR '}' * ``` @@ -241,65 +288,68 @@ module.exports = { * $foo[123]{1}; // gets the 2nd char from the 123 array entry * */ - ,read_reference_variable: function(encapsed, byref) { - var result = this.read_simple_variable(byref); - while(this.token != this.EOF) { - var node = this.node(); - if (this.token == '[') { - var offset = null; - if (encapsed) { - offset = this.next().read_encaps_var_offset(); - } else { - offset = this.next().token === ']' ? null : this.read_dim_offset(); - } - this.expect(']') && this.next(); - result = node('offsetlookup', result, offset); - } else if (this.token == '{' && !encapsed) { - var offset = this.next().read_expr(); - this.expect('}') && this.next(); - result = node('offsetlookup', result, offset); - } else break; + read_reference_variable: function (encapsed) { + let result = this.read_simple_variable(); + let offset; + while (this.token != this.EOF) { + const node = this.node(); + if (this.token == "{" && !encapsed) { + // @fixme check coverage, not sure thats working + offset = this.next().read_expr(); + this.expect("}") && this.next(); + result = node("offsetlookup", result, offset); + } else { + node.destroy(); + break; + } } return result; - } - /** + }, + /* * ```ebnf * simple_variable ::= T_VARIABLE | '$' '{' expr '}' | '$' simple_variable * ``` */ - ,read_simple_variable: function(byref) { - var result = this.node('variable'); - if (this.expect([this.tok.T_VARIABLE, '$']) && this.token === this.tok.T_VARIABLE) { + read_simple_variable: function () { + let result = this.node("variable"); + let name; + if ( + this.expect([this.tok.T_VARIABLE, "$"]) && + this.token === this.tok.T_VARIABLE + ) { // plain variable name - var name = this.text().substring(1); + name = this.text().substring(1); this.next(); - result = result(name, byref, false); + result = result(name, false); } else { - if (this.token === '$') this.next(); + if (this.token === "$") this.next(); // dynamic variable name - switch(this.token) { - case '{': - var expr = this.next().read_expr(); - this.expect('}') && this.next(); - result = result(expr, byref, true); + switch (this.token) { + case "{": { + const expr = this.next().read_expr(); + this.expect("}") && this.next(); + result = result(expr, true); break; - case '$': // $$$var - result = result(this.read_simple_variable(false), byref); + } + case "$": // $$$var + result = result(this.read_simple_variable(), false); break; - case this.tok.T_VARIABLE: // $$var - var name = this.text().substring(1); - var node = this.node('variable'); + case this.tok.T_VARIABLE: { + // $$var + name = this.text().substring(1); + const node = this.node("variable"); this.next(); - result = result(node(name, false, false), byref, false); + result = result(node(name, false), false); break; + } default: - this.error(['{', '$', this.tok.T_VARIABLE]); + this.error(["{", "$", this.tok.T_VARIABLE]); // graceful mode - var name = this.text(); + name = this.text(); this.next(); - result = result(name, byref, false); + result = result(name, false); } } return result; - } + }, }; diff --git a/src/tokens.js b/src/tokens.js index 26e9ed445..fbb5e220c 100644 --- a/src/tokens.js +++ b/src/tokens.js @@ -1,279 +1,177 @@ -/*! - * Copyright (C) 2017 Glayzzle (BSD3 License) +/** + * Copyright (C) 2018 Glayzzle (BSD3 License) * @authors https://github.com/glayzzle/php-parser/graphs/contributors * @url http://glayzzle.com */ +"use strict"; -// exports token index -module.exports = { - values: { - 101: 'T_HALT_COMPILER', - 102: 'T_USE', - 103: 'T_ENCAPSED_AND_WHITESPACE', - 104: 'T_OBJECT_OPERATOR', - 105: 'T_STRING', - 106: 'T_DOLLAR_OPEN_CURLY_BRACES', - 107: 'T_STRING_VARNAME', - 108: 'T_CURLY_OPEN', - 109: 'T_NUM_STRING', - 110: 'T_ISSET', - 111: 'T_EMPTY', - 112: 'T_INCLUDE', - 113: 'T_INCLUDE_ONCE', - 114: 'T_EVAL', - 115: 'T_REQUIRE', - 116: 'T_REQUIRE_ONCE', - 117: 'T_NAMESPACE', - 118: 'T_NS_SEPARATOR', - 119: 'T_AS', - 120: 'T_IF', - 121: 'T_ENDIF', - 122: 'T_WHILE', - 123: 'T_DO', - 124: 'T_FOR', - 125: 'T_SWITCH', - 126: 'T_BREAK', - 127: 'T_CONTINUE', - 128: 'T_RETURN', - 129: 'T_GLOBAL', - 130: 'T_STATIC', - 131: 'T_ECHO', - 132: 'T_INLINE_HTML', - 133: 'T_UNSET', - 134: 'T_FOREACH', - 135: 'T_DECLARE', - 136: 'T_TRY', - 137: 'T_THROW', - 138: 'T_GOTO', - 139: 'T_FINALLY', - 140: 'T_CATCH', - 141: 'T_ENDDECLARE', - 142: 'T_LIST', - 143: 'T_CLONE', - 144: 'T_PLUS_EQUAL', - 145: 'T_MINUS_EQUAL', - 146: 'T_MUL_EQUAL', - 147: 'T_DIV_EQUAL', - 148: 'T_CONCAT_EQUAL', - 149: 'T_MOD_EQUAL', - 150: 'T_AND_EQUAL', - 151: 'T_OR_EQUAL', - 152: 'T_XOR_EQUAL', - 153: 'T_SL_EQUAL', - 154: 'T_SR_EQUAL', - 155: 'T_INC', - 156: 'T_DEC', - 157: 'T_BOOLEAN_OR', - 158: 'T_BOOLEAN_AND', - 159: 'T_LOGICAL_OR', - 160: 'T_LOGICAL_AND', - 161: 'T_LOGICAL_XOR', - 162: 'T_SL', - 163: 'T_SR', - 164: 'T_IS_IDENTICAL', - 165: 'T_IS_NOT_IDENTICAL', - 166: 'T_IS_EQUAL', - 167: 'T_IS_NOT_EQUAL', - 168: 'T_IS_SMALLER_OR_EQUAL', - 169: 'T_IS_GREATER_OR_EQUAL', - 170: 'T_INSTANCEOF', - 171: 'T_INT_CAST', - 172: 'T_DOUBLE_CAST', - 173: 'T_STRING_CAST', - 174: 'T_ARRAY_CAST', - 175: 'T_OBJECT_CAST', - 176: 'T_BOOL_CAST', - 177: 'T_UNSET_CAST', - 178: 'T_EXIT', - 179: 'T_PRINT', - 180: 'T_YIELD', - 181: 'T_YIELD_FROM', - 182: 'T_FUNCTION', - 183: 'T_DOUBLE_ARROW', - 184: 'T_DOUBLE_COLON', - 185: 'T_ARRAY', - 186: 'T_CALLABLE', - 187: 'T_CLASS', - 188: 'T_ABSTRACT', - 189: 'T_TRAIT', - 190: 'T_FINAL', - 191: 'T_EXTENDS', - 192: 'T_INTERFACE', - 193: 'T_IMPLEMENTS', - 194: 'T_VAR', - 195: 'T_PUBLIC', - 196: 'T_PROTECTED', - 197: 'T_PRIVATE', - 198: 'T_CONST', - 199: 'T_NEW', - 200: 'T_INSTEADOF', - 201: 'T_ELSEIF', - 202: 'T_ELSE', - 203: 'T_ENDSWITCH', - 204: 'T_CASE', - 205: 'T_DEFAULT', - 206: 'T_ENDFOR', - 207: 'T_ENDFOREACH', - 208: 'T_ENDWHILE', - 209: 'T_CONSTANT_ENCAPSED_STRING', - 210: 'T_LNUMBER', - 211: 'T_DNUMBER', - 212: 'T_LINE', - 213: 'T_FILE', - 214: 'T_DIR', - 215: 'T_TRAIT_C', - 216: 'T_METHOD_C', - 217: 'T_FUNC_C', - 218: 'T_NS_C', - 219: 'T_START_HEREDOC', - 220: 'T_END_HEREDOC', - 221: 'T_CLASS_C', - 222: 'T_VARIABLE', - 223: 'T_OPEN_TAG', - 224: 'T_OPEN_TAG_WITH_ECHO', - 225: 'T_CLOSE_TAG', - 226: 'T_WHITESPACE', - 227: 'T_COMMENT', - 228: 'T_DOC_COMMENT', - 229: 'T_ELLIPSIS', - 230: 'T_COALESCE', - 231: 'T_POW', - 232: 'T_POW_EQUAL', - 233: 'T_SPACESHIP' - }, - names: { - T_HALT_COMPILER: 101, - T_USE: 102, - T_ENCAPSED_AND_WHITESPACE: 103, - T_OBJECT_OPERATOR: 104, - T_STRING: 105, - T_DOLLAR_OPEN_CURLY_BRACES: 106, - T_STRING_VARNAME: 107, - T_CURLY_OPEN: 108, - T_NUM_STRING: 109, - T_ISSET: 110, - T_EMPTY: 111, - T_INCLUDE: 112, - T_INCLUDE_ONCE: 113, - T_EVAL: 114, - T_REQUIRE: 115, - T_REQUIRE_ONCE: 116, - T_NAMESPACE: 117, - T_NS_SEPARATOR: 118, - T_AS: 119, - T_IF: 120, - T_ENDIF: 121, - T_WHILE: 122, - T_DO: 123, - T_FOR: 124, - T_SWITCH: 125, - T_BREAK: 126, - T_CONTINUE: 127, - T_RETURN: 128, - T_GLOBAL: 129, - T_STATIC: 130, - T_ECHO: 131, - T_INLINE_HTML: 132, - T_UNSET: 133, - T_FOREACH: 134, - T_DECLARE: 135, - T_TRY: 136, - T_THROW: 137, - T_GOTO: 138, - T_FINALLY: 139, - T_CATCH: 140, - T_ENDDECLARE: 141, - T_LIST: 142, - T_CLONE: 143, - T_PLUS_EQUAL: 144, - T_MINUS_EQUAL: 145, - T_MUL_EQUAL: 146, - T_DIV_EQUAL: 147, - T_CONCAT_EQUAL: 148, - T_MOD_EQUAL: 149, - T_AND_EQUAL: 150, - T_OR_EQUAL: 151, - T_XOR_EQUAL: 152, - T_SL_EQUAL: 153, - T_SR_EQUAL: 154, - T_INC: 155, - T_DEC: 156, - T_BOOLEAN_OR: 157, - T_BOOLEAN_AND: 158, - T_LOGICAL_OR: 159, - T_LOGICAL_AND: 160, - T_LOGICAL_XOR: 161, - T_SL: 162, - T_SR: 163, - T_IS_IDENTICAL: 164, - T_IS_NOT_IDENTICAL: 165, - T_IS_EQUAL: 166, - T_IS_NOT_EQUAL: 167, - T_IS_SMALLER_OR_EQUAL: 168, - T_IS_GREATER_OR_EQUAL: 169, - T_INSTANCEOF: 170, - T_INT_CAST: 171, - T_DOUBLE_CAST: 172, - T_STRING_CAST: 173, - T_ARRAY_CAST: 174, - T_OBJECT_CAST: 175, - T_BOOL_CAST: 176, - T_UNSET_CAST: 177, - T_EXIT: 178, - T_PRINT: 179, - T_YIELD: 180, - T_YIELD_FROM: 181, - T_FUNCTION: 182, - T_DOUBLE_ARROW: 183, - T_DOUBLE_COLON: 184, - T_ARRAY: 185, - T_CALLABLE: 186, - T_CLASS: 187, - T_ABSTRACT: 188, - T_TRAIT: 189, - T_FINAL: 190, - T_EXTENDS: 191, - T_INTERFACE: 192, - T_IMPLEMENTS: 193, - T_VAR: 194, - T_PUBLIC: 195, - T_PROTECTED: 196, - T_PRIVATE: 197, - T_CONST: 198, - T_NEW: 199, - T_INSTEADOF: 200, - T_ELSEIF: 201, - T_ELSE: 202, - T_ENDSWITCH: 203, - T_CASE: 204, - T_DEFAULT: 205, - T_ENDFOR: 206, - T_ENDFOREACH: 207, - T_ENDWHILE: 208, - T_CONSTANT_ENCAPSED_STRING: 209, - T_LNUMBER: 210, - T_DNUMBER: 211, - T_LINE: 212, - T_FILE: 213, - T_DIR: 214, - T_TRAIT_C: 215, - T_METHOD_C: 216, - T_FUNC_C: 217, - T_NS_C: 218, - T_START_HEREDOC: 219, - T_END_HEREDOC: 220, - T_CLASS_C: 221, - T_VARIABLE: 222, - T_OPEN_TAG: 223, - T_OPEN_TAG_WITH_ECHO: 224, - T_CLOSE_TAG: 225, - T_WHITESPACE: 226, - T_COMMENT: 227, - T_DOC_COMMENT: 228, - T_ELLIPSIS: 229, - T_COALESCE: 230, - T_POW: 231, - T_POW_EQUAL: 232, - T_SPACESHIP: 233 - } +/** + * @readonly + * @memberOf module:php-parser + * + * @enum {number} + **/ +const TokenNames = { + T_HALT_COMPILER: 101, + T_USE: 102, + T_ENCAPSED_AND_WHITESPACE: 103, + T_OBJECT_OPERATOR: 104, + T_STRING: 105, + T_DOLLAR_OPEN_CURLY_BRACES: 106, + T_STRING_VARNAME: 107, + T_CURLY_OPEN: 108, + T_NUM_STRING: 109, + T_ISSET: 110, + T_EMPTY: 111, + T_INCLUDE: 112, + T_INCLUDE_ONCE: 113, + T_EVAL: 114, + T_REQUIRE: 115, + T_REQUIRE_ONCE: 116, + T_NAMESPACE: 117, + T_NS_SEPARATOR: 118, + T_AS: 119, + T_IF: 120, + T_ENDIF: 121, + T_WHILE: 122, + T_DO: 123, + T_FOR: 124, + T_SWITCH: 125, + T_BREAK: 126, + T_CONTINUE: 127, + T_RETURN: 128, + T_GLOBAL: 129, + T_STATIC: 130, + T_ECHO: 131, + T_INLINE_HTML: 132, + T_UNSET: 133, + T_FOREACH: 134, + T_DECLARE: 135, + T_TRY: 136, + T_THROW: 137, + T_GOTO: 138, + T_FINALLY: 139, + T_CATCH: 140, + T_ENDDECLARE: 141, + T_LIST: 142, + T_CLONE: 143, + T_PLUS_EQUAL: 144, + T_MINUS_EQUAL: 145, + T_MUL_EQUAL: 146, + T_DIV_EQUAL: 147, + T_CONCAT_EQUAL: 148, + T_MOD_EQUAL: 149, + T_AND_EQUAL: 150, + T_OR_EQUAL: 151, + T_XOR_EQUAL: 152, + T_SL_EQUAL: 153, + T_SR_EQUAL: 154, + T_INC: 155, + T_DEC: 156, + T_BOOLEAN_OR: 157, + T_BOOLEAN_AND: 158, + T_LOGICAL_OR: 159, + T_LOGICAL_AND: 160, + T_LOGICAL_XOR: 161, + T_SL: 162, + T_SR: 163, + T_IS_IDENTICAL: 164, + T_IS_NOT_IDENTICAL: 165, + T_IS_EQUAL: 166, + T_IS_NOT_EQUAL: 167, + T_IS_SMALLER_OR_EQUAL: 168, + T_IS_GREATER_OR_EQUAL: 169, + T_INSTANCEOF: 170, + T_INT_CAST: 171, + T_DOUBLE_CAST: 172, + T_STRING_CAST: 173, + T_ARRAY_CAST: 174, + T_OBJECT_CAST: 175, + T_BOOL_CAST: 176, + T_UNSET_CAST: 177, + T_EXIT: 178, + T_PRINT: 179, + T_YIELD: 180, + T_YIELD_FROM: 181, + T_FUNCTION: 182, + T_DOUBLE_ARROW: 183, + T_DOUBLE_COLON: 184, + T_ARRAY: 185, + T_CALLABLE: 186, + T_CLASS: 187, + T_ABSTRACT: 188, + T_TRAIT: 189, + T_FINAL: 190, + T_EXTENDS: 191, + T_INTERFACE: 192, + T_IMPLEMENTS: 193, + T_VAR: 194, + T_PUBLIC: 195, + T_PROTECTED: 196, + T_PRIVATE: 197, + T_CONST: 198, + T_NEW: 199, + T_INSTEADOF: 200, + T_ELSEIF: 201, + T_ELSE: 202, + T_ENDSWITCH: 203, + T_CASE: 204, + T_DEFAULT: 205, + T_ENDFOR: 206, + T_ENDFOREACH: 207, + T_ENDWHILE: 208, + T_CONSTANT_ENCAPSED_STRING: 209, + T_LNUMBER: 210, + T_DNUMBER: 211, + T_LINE: 212, + T_FILE: 213, + T_DIR: 214, + T_TRAIT_C: 215, + T_METHOD_C: 216, + T_FUNC_C: 217, + T_NS_C: 218, + T_START_HEREDOC: 219, + T_END_HEREDOC: 220, + T_CLASS_C: 221, + T_VARIABLE: 222, + T_OPEN_TAG: 223, + T_OPEN_TAG_WITH_ECHO: 224, + T_CLOSE_TAG: 225, + T_WHITESPACE: 226, + T_COMMENT: 227, + T_DOC_COMMENT: 228, + T_ELLIPSIS: 229, + T_COALESCE: 230, + T_POW: 231, + T_POW_EQUAL: 232, + T_SPACESHIP: 233, + T_COALESCE_EQUAL: 234, + T_FN: 235, + T_NULLSAFE_OBJECT_OPERATOR: 236, + T_MATCH: 237, + T_ATTRIBUTE: 238, + T_ENUM: 239, + T_READ_ONLY: 240, + T_NAME_RELATIVE: 241, + T_NAME_QUALIFIED: 242, + T_NAME_FULLY_QUALIFIED: 243, }; + +/** + * PHP AST Tokens + * @readonly + * @memberOf module:php-parser + * + * @type {object} + * @property {Object.} values + * @property {TokenNames} names + */ +const tokens = { + values: Object.entries(TokenNames).reduce( + (result, [key, value]) => ({ ...result, [value]: key }), + {}, + ), + names: TokenNames, +}; + +module.exports = Object.freeze(tokens); diff --git a/test/arrayTests.js b/test/arrayTests.js deleted file mode 100644 index 42ccc052c..000000000 --- a/test/arrayTests.js +++ /dev/null @@ -1,202 +0,0 @@ -var should = require("should"); -var parser = require('../src/index'); - -describe('Array without keys', function() { - - it('deference array', function () { - var ast = parser.parseEval([ - '$a = [', - '"a", "b"', - ']($foo)[$foo->bar()[1]]->foo()' - ].join('\r'), { - parser: { - // debug: true - } - }); - // @todo console.log(ast); - }); - - describe('of strings', function () { - // Get result from parser - var ast = parser.parseEval('array("item1", "item2", "item3")'); - - it('should be of type array', function () { - ast.children[0].kind.should.be.exactly("array"); - }); - - it('should have correct number of items', function () { - ast.children[0].items.length.should.be.exactly(3); - }); - - it('should have correct item types and values', function () { - ast.children[0].items[0].value.kind.should.be.exactly("string"); - ast.children[0].items[0].value.value.should.be.exactly("item1"); - - ast.children[0].items[1].value.kind.should.be.exactly("string"); - ast.children[0].items[1].value.value.should.be.exactly("item2"); - - ast.children[0].items[2].value.kind.should.be.exactly("string"); - ast.children[0].items[2].value.value.should.be.exactly("item3"); - }); - }); - - describe('of numbers', function () { - // Get result from parser - var ast = parser.parseEval('array(1, 2.5, 0x1000)'); - - it('should be of type array', function () { - ast.children[0].kind.should.be.exactly("array"); - }); - - it('should have correct number of items', function () { - ast.children[0].items.length.should.be.exactly(3); - }); - - it('should have correct item types and values', function () { - ast.children[0].items[0].value.kind.should.be.exactly("number"); - ast.children[0].items[0].value.value.should.be.exactly('1'); - - ast.children[0].items[1].value.kind.should.be.exactly("number"); - ast.children[0].items[1].value.value.should.be.exactly('2.5'); - - ast.children[0].items[2].value.kind.should.be.exactly("number"); - ast.children[0].items[2].value.value.should.be.exactly('0x1000'); - }); - }); - - describe('of strings and numbers', function () { - // Get result from parser - var ast = parser.parseEval('array(1, "item2", 3, "item4")'); - - it('should be of type array', function () { - ast.children[0].kind.should.be.exactly("array"); - }); - - it('should have correct number of items', function () { - ast.children[0].items.length.should.be.exactly(4); - }); - - it('should have correct item types and values', function () { - ast.children[0].items[0].value.kind.should.be.exactly("number"); - ast.children[0].items[0].value.value.should.be.exactly('1'); - - ast.children[0].items[1].value.kind.should.be.exactly("string"); - ast.children[0].items[1].value.value.should.be.exactly("item2"); - - ast.children[0].items[2].value.kind.should.be.exactly("number"); - ast.children[0].items[2].value.value.should.be.exactly('3'); - - ast.children[0].items[3].value.kind.should.be.exactly("string"); - ast.children[0].items[3].value.value.should.be.exactly("item4"); - }); - }); - - describe('of variables', function () { - // Get result from parser - var ast = parser.parseEval('array($obj1, $obj2, $obj3)'); - - it('should be of type array', function () { - ast.children[0].kind.should.be.exactly("array"); - }); - - it('should have correct number of items', function () { - ast.children[0].items.length.should.be.exactly(3); - }); - - it('should have correct item types and values', function () { - ast.children[0].items[0].value.kind.should.be.exactly("variable"); - ast.children[0].items[0].value.name.should.be.exactly("obj1"); - - ast.children[0].items[1].value.kind.should.be.exactly("variable"); - ast.children[0].items[1].value.name.should.be.exactly("obj2"); - - ast.children[0].items[2].value.kind.should.be.exactly("variable"); - ast.children[0].items[2].value.name.should.be.exactly("obj3"); - }); - }); - - // TODO -- Check this is valid PHP + check AST output is correct - describe('of objects', function () { - // Get result from parser - var ast = parser.parseEval('[new foo(), new stdClass(), new bar()]'); - - it('should be of type array', function () { - ast.children[0].kind.should.be.exactly("array"); - }); - - it('should have correct number of items', function () { - ast.children[0].items.length.should.be.exactly(3); - }); - - it('should have correct item types and values', function () { - ast.children[0].items[0].value.kind.should.be.exactly("new"); - ast.children[0].items[0].value.what.name.should.be.exactly("foo"); - - ast.children[0].items[1].value.kind.should.be.exactly("new"); - ast.children[0].items[1].value.what.name.should.be.exactly("stdClass"); - - ast.children[0].items[2].value.kind.should.be.exactly("new"); - ast.children[0].items[2].value.what.name.should.be.exactly("bar"); - }); - }); - - describe('of arrays', function () { - // Get result from parser - var ast = parser.parseEval([ - 'array(', - ' array("item1", "item2"),', - ' array("item3", "item4"),', - ' array("item5", "item6")', - ')' - ].join('\n')); - - it('should be of type array', function () { - ast.children[0].kind.should.be.exactly("array"); - }); - - it('should have correct number of items', function () { - ast.children[0].items.length.should.be.exactly(3); - }); - - it('should have correct item types and values', function () { - ast.children[0].items[0].value.kind.should.be.exactly("array"); - ast.children[0].items[0].value.items.length.should.be.exactly(2); - ast.children[0].items[0].value.items[0].value.value.should.be.exactly("item1"); - ast.children[0].items[0].value.items[1].value.value.should.be.exactly("item2"); - - ast.children[0].items[1].value.kind.should.be.exactly("array"); - ast.children[0].items[1].value.items.length.should.be.exactly(2); - ast.children[0].items[1].value.items[0].value.value.should.be.exactly("item3"); - ast.children[0].items[1].value.items[1].value.value.should.be.exactly("item4"); - - ast.children[0].items[2].value.kind.should.be.exactly("array"); - ast.children[0].items[2].value.items.length.should.be.exactly(2); - ast.children[0].items[2].value.items[0].value.value.should.be.exactly("item5"); - ast.children[0].items[2].value.items[1].value.value.should.be.exactly("item6"); - }); - }); - - describe('mixed tests / coverage', function() { - it('test empty array', function() { - var ast = parser.parseEval('$a = []; $b = array();'); - ast.children[0].right.items.length.should.be.exactly(0); - ast.children[1].right.items.length.should.be.exactly(0); - }); - it('test short form / keys', function() { - var ast = parser.parseEval('[0 => &$foo, $bar => "foobar"];'); - ast.children[0].items.length.should.be.exactly(2); - ast.children[0].shortForm.should.be.exactly(true); - ast.children[0].items[0].key.kind.should.be.exactly('number'); - ast.children[0].items[0].value.kind.should.be.exactly('variable'); - ast.children[0].items[0].value.byref.should.be.exactly(true); - ast.children[0].items[0].value.name.should.be.exactly('foo'); - ast.children[0].items[0].value.byref.should.be.exactly(true); - ast.children[0].items[1].key.kind.should.be.exactly('variable'); - ast.children[0].items[1].key.name.should.be.exactly('bar'); - ast.children[0].items[1].key.byref.should.be.exactly(false); - }); - - }); - - -}); diff --git a/test/ast.test.js b/test/ast.test.js new file mode 100644 index 000000000..863f6f1df --- /dev/null +++ b/test/ast.test.js @@ -0,0 +1,45 @@ +const parser = require("./main"); + +describe("Test AST class (edge cases)", function () { + it("test source without location", function () { + const test = parser.create({ + ast: { + withPositions: false, + withSource: true, + }, + }); + const ast = test.parseEval("echo $foo;"); + const echo = ast.children[0]; + expect(echo.loc.source).toBe("echo $foo;"); + expect(echo.loc.start).not.toBeNull(); + expect(echo.loc.end).not.toBeNull(); + + const variable = echo.expressions[0]; + expect(variable.loc.source).toBe("$foo"); + }); + it("test undefined node", function () { + const test = parser.create(); + expect(() => { + const node = test.parser.node("foo"); + node(); + }).toThrow(/foo/); + }); + it("test debug mode", function () { + const test = parser.create({ + parser: { + debug: true, + }, + }); + test.parseEval("1 + 1;"); + }); + it("test debug mode / errors", function () { + const test = parser.create({ + parser: { + debug: true, + }, + }); + expect(() => { + test.parseEval("1 + ;"); + }).toThrow(); + }); +}); diff --git a/test/astTests.js b/test/astTests.js deleted file mode 100644 index 6f4330d74..000000000 --- a/test/astTests.js +++ /dev/null @@ -1,140 +0,0 @@ -var should = require("should"); -var parser = require('./main'); - -describe('Test AST structure', function() { - - it('test program', function() { - var ast = parser.parseEval(''); - ast.kind.should.be.exactly('program'); - ast.children.length.should.be.exactly(0); - }); - - - it('test syntax error', function() { - var err = null; - (function(){ - try { - var ast = parser.parseCode([ - ' !'); - ast.children[0].kind.should.be.exactly('inline'); - ast.children[2].kind.should.be.exactly('inline'); - ast.children[0].value.should.be.exactly('Hello '); - ast.children[2].value.should.be.exactly(' !'); - }); - - it('test magics', function() { - var ast = parser.parseEval('echo __FILE__, __DIR__;'); - ast.children[0].arguments[0].kind.should.be.exactly('magic'); - ast.children[0].arguments[1].kind.should.be.exactly('magic'); - ast.children[0].arguments[0].value.should.be.exactly('__FILE__'); - ast.children[0].arguments[1].value.should.be.exactly('__DIR__'); - }); - it('test shell', function() { - var ast = parser.parseEval('echo `ls -larth`;'); - ast.children[0].arguments[0].kind.should.be.exactly('encapsed'); - ast.children[0].arguments[0].type.should.be.exactly('shell'); - }); - it('test clone', function() { - var ast = parser.parseEval('$a = clone $var;'); - ast.children[0].right.kind.should.be.exactly('clone'); - ast.children[0].right.what.kind.should.be.exactly('variable'); - }); - it('test echo, isset, unset, empty', function() { - var ast = parser.parseEval([ - 'echo ($expr) ? "ok" : "ko";', - 'print "some text"', - 'isset($foo, $bar)', - 'unset($var)', - 'empty($var)', - '' - ].join(';\n')); - ast.children[0].kind.should.be.exactly('echo'); - ast.children[1].kind.should.be.exactly('print'); - ast.children[2].kind.should.be.exactly('isset'); - ast.children[3].kind.should.be.exactly('unset'); - ast.children[4].kind.should.be.exactly('empty'); - }); - - it('should be variable', function() { - // @todo - }); - it('test literals', function() { - // @todo string / numbers / booleans - }); - - it('test constants', function() { - var ast = parser.parseEval('const FOO = 3.14;'); - ast.children[0].kind.should.be.exactly('constant'); - ast.children[0].name.should.be.exactly('FOO'); - ast.children[0].value.kind.should.be.exactly('number'); - ast.children[0].value.value.should.be.exactly('3.14'); - }); - - it('test eval', function() { - var ast = parser.parseEval('eval("return true;");'); - ast.children[0].kind.should.be.exactly('eval'); - ast.children[0].source.kind.should.be.exactly('string'); - ast.children[0].source.value.should.be.exactly('return true;'); - }); - it('test die/exit', function() { - var ast = parser.parseEval('die("bye");'); - ast.children[0].kind.should.be.exactly('exit'); - ast.children[0].status.value.should.be.exactly('bye'); - ast = parser.parseEval('exit(-1);'); - ast.children[0].kind.should.be.exactly('exit'); - ast.children[0].status.value.should.be.exactly('-1'); - }); - - it('test coalesce operator', function() { - var ast = parser.parseEval('$var = $a ?? true;'); - ast.children[0].right.kind.should.be.exactly('bin'); - ast.children[0].right.type.should.be.exactly('??'); - ast.children[0].right.left.kind.should.be.exactly('variable'); - ast.children[0].right.right.kind.should.be.exactly('boolean'); - }); - - it('test include / require', function() { - var ast = parser.parseEval([ - 'include "file.php"', - 'include_once (PATH . "/file.php")', - 'require "req.php"', - 'require_once "file.php"', - '' - ].join(';\n')); - - ast.children[0].kind.should.be.exactly('include'); - ast.children[0].once.should.be.exactly(false); - ast.children[0].require.should.be.exactly(false); - - ast.children[1].kind.should.be.exactly('include'); - ast.children[1].once.should.be.exactly(true); - ast.children[1].require.should.be.exactly(false); - - ast.children[2].kind.should.be.exactly('include'); - ast.children[2].once.should.be.exactly(false); - ast.children[2].require.should.be.exactly(true); - - ast.children[3].kind.should.be.exactly('include'); - ast.children[3].once.should.be.exactly(true); - ast.children[3].require.should.be.exactly(true); - - }); - - -}); diff --git a/test/benchmark.js b/test/benchmark.js new file mode 100644 index 000000000..8cf22c747 --- /dev/null +++ b/test/benchmark.js @@ -0,0 +1,31 @@ +const parser = require("./main"); +const Benchmark = require("benchmark"); +const suite = new Benchmark.Suite(); + +const code = ` + { + console.log(String(event.target)); +}); +suite.run(); diff --git a/test/benchmark2.js b/test/benchmark2.js new file mode 100644 index 000000000..d03e6cee7 --- /dev/null +++ b/test/benchmark2.js @@ -0,0 +1,18 @@ +const parser = require("./main"); + +const code = ` + data = $data;', - ' }', - '}', - 'abstract class bar {', - ' use A, B {', - ' B::smallTalk insteadof A;', - ' A::bigTalk insteadof B, C;', - ' B::bigTalk as public talk;', - ' B::bigTalk as protected talk;', - ' B::bigTalk as private talk;', - ' }', - ' /**', - ' * Some informations', - ' */', - ' abstract protected function &foo() : bar;', - '}' - ].join('\n'), { - parser: { debug: false } - }); - - it('test program size', function() { - ast.children.length.should.be.exactly(2); - }); - - it('test kind', function() { - ast.children[0].kind.should.be.exactly('class'); - ast.children[1].kind.should.be.exactly('class'); - }); - - it('test names', function() { - ast.children[0].name.should.be.exactly('foo'); - ast.children[1].name.should.be.exactly('bar'); - }); - - it('test flags', function() { - ast.children[0].isFinal.should.be.exactly(true); - ast.children[0].isAbstract.should.be.exactly(false); - ast.children[0].isAnonymous.should.be.exactly(false); - ast.children[1].isFinal.should.be.exactly(false); - ast.children[1].isAbstract.should.be.exactly(true); - ast.children[1].isAnonymous.should.be.exactly(false); - }); - - it('test extends', function() { - ast.children[0].extends.name.should.be.exactly('bar'); - should.equal(ast.children[1].extends, null); - }); - - it('test implements', function() { - ast.children[0].implements.length.should.be.exactly(3); - ast.children[0].implements[0].name.should.be.exactly('bim'); - ast.children[0].implements[1].name.should.be.exactly('bam'); - ast.children[0].implements[2].name.should.be.exactly('boum'); - should.equal(ast.children[1].implements, null); - }); - - it('test trait usage', function() { - var use = ast.children[1].body[0]; - /** - ' use A, B {', - ' B::smallTalk insteadof A;', - ' A::bigTalk insteadof B, C;', - ' B::bigTalk as protected talk;', - ' }', - */ - use.kind.should.be.exactly('traituse'); - // test traits names - use.traits.length.should.be.exactly(2); - use.traits[0].name.should.be.exactly('A'); - use.traits[1].name.should.be.exactly('B'); - // test adaptations - use.adaptations.length.should.be.exactly(5); - use.adaptations[0].kind.should.be.exactly('traitprecedence'); - use.adaptations[1].kind.should.be.exactly('traitprecedence'); - use.adaptations[2].kind.should.be.exactly('traitalias'); - - // test adaptation contents - use.adaptations[0].trait.name.should.be.exactly('B'); - use.adaptations[0].method.should.be.exactly('smallTalk'); - use.adaptations[0].instead[0].name.should.be.exactly('A'); - - // test adaptation contents - use.adaptations[1].trait.name.should.be.exactly('A'); - use.adaptations[1].method.should.be.exactly('bigTalk'); - use.adaptations[1].instead[0].name.should.be.exactly('B'); - use.adaptations[1].instead[1].name.should.be.exactly('C'); - - // test adaptation contents - use.adaptations[2].trait.name.should.be.exactly('B'); - use.adaptations[2].method.should.be.exactly('bigTalk'); - use.adaptations[2].as.should.be.exactly('talk'); - use.adaptations[2].visibility.should.be.exactly('public'); - use.adaptations[3].visibility.should.be.exactly('protected'); - use.adaptations[4].visibility.should.be.exactly('private'); - - }); - - it('test methods', function() { - var method = ast.children[1].body[1]; - method.kind.should.be.exactly('method'); - method.isStatic.should.be.exactly(false); - method.isFinal.should.be.exactly(false); - method.isAbstract.should.be.exactly(true); - method.visibility.should.be.exactly('protected'); - method.name.should.be.exactly('foo'); - method.byref.should.be.exactly(true); - // no arguments - method.arguments.length.should.be.exactly(0); - // no body - should.equal(method.body, null); - // check return type - method.type.name.should.be.exactly('bar'); - }); - }); - - describe('Advanced tests', function() { - var ast = parser.parseEval([ - 'class foo implements boo {', - ' use A;', - ' use B { foo as bar; }', - ' // comment', - ' /* boo */', - ' /** doc', - ' * data', - ' foo', - ' */', - ' var $var = true;', - ' final function __construct() { }', - ' private function boo() { }', - '}', - 'interface boo extends something {', - ' // some doc', - ' const A = 1.5;', - ' /** foo */', - ' protected function foo();', - '}', - 'trait line extends foo implements boo {', - ' // some doc', - ' const A = 1.5;', - ' abstract protected function foo();', - '}' - ].join('\n'), { - parser: { extractDoc: true } - }); - - it('check comments', function() { - // @todo - }); - - it('check interface', function() { - // @todo - }); - - it('check traits', function() { - // @todo - }); - - }); - - describe('Test of silent mode', function() { - var ast = parser.parseEval([ - 'class foo {', - ' use A', - ' use B { foo };', - '}' - ].join('\n'), { - parser: { suppressErrors: true } - }); - - it('check use statement errors', function() { - // @todo - }); - }); -}); diff --git a/test/commentTests.js b/test/commentTests.js deleted file mode 100644 index 25b8d6e2c..000000000 --- a/test/commentTests.js +++ /dev/null @@ -1,199 +0,0 @@ -var should = require("should"); -var parser = require('../src/index'); - -describe('Test comments', function() { - - describe('issues', function () { - it('fix #55', function () { - var ast = parser.parseEval([ - 'if (true):', - ' if (true):', - ' // inner statements', - ' endif; // another comment', - 'endif; // 2nd comment' - ].join('\n'), { - parser: { - extractDoc: true, - // debug: true - } - }); - ast.children.length.should.be.exactly(2); - ast.children[0].kind.should.be.exactly('if'); - ast.children[0].body.children.length.should.be.exactly(2); - ast.children[0].body.children[0].kind.should.be.exactly('if'); - ast.children[0].body.children[1].kind.should.be.exactly('doc'); - ast.children[0].body.children[1].lines[0].should.be.exactly('another comment'); - ast.children[1].kind.should.be.exactly('doc'); - ast.children[1].lines[0].should.be.exactly('2nd comment'); - }); - }); - - describe('single line comments', function () { - var ast = parser.parseEval([ - '# some information', - '// another line', - '$foo = 123 // 123', - '; /* done */' - ].join('\n'), { - parser: { - extractDoc: true - } - }); - it('test cummulative array', function () { - ast.children.length.should.be.exactly(3); - ast.children[0].kind.should.be.exactly("doc"); - ast.children[0].isDoc.should.be.exactly(false); - ast.children[0].lines.length.should.be.exactly(2); - ast.children[0].lines[0].should.be.exactly('some information'); - ast.children[0].lines[1].should.be.exactly('another line'); - }); - it('test statements', function () { - ast.children[2].kind.should.be.exactly("doc"); - ast.children[2].isDoc.should.be.exactly(false); - ast.children[2].lines[0].should.be.exactly('done'); - }); - it('ignore comments in expression', function () { - ast.children[1].kind.should.be.exactly("assign"); - ast.children[1].left.kind.should.be.exactly('variable'); - ast.children[1].right.kind.should.be.exactly('number'); - }); - }); - - describe('multi line comments', function () { - - var ast = parser.parseEval([ - '/**', - ' * Description', - ' */', - 'function /* ignore */ name(/* */ $arg) {', - '// inner', - 'return $arg /* ignore */;', - '}' - ].join('\n'), { - parser: { - extractDoc: true - } - }); - it('test statements', function () { - ast.children[0].kind.should.be.exactly("doc"); - ast.children[0].lines.length.should.be.exactly(3); - ast.children[0].lines[0].should.be.exactly(''); - ast.children[0].lines[1].should.be.exactly('Description'); - ast.children[0].lines[2].should.be.exactly(''); - }); - it('test function', function () { - ast.children[1].kind.should.be.exactly("function"); - ast.children[1].name.should.be.exactly("name"); - ast.children[1].arguments.length.should.be.exactly(1); - var body = ast.children[1].body.children; - body[0].kind.should.be.exactly('doc'); - // @todo body[1].kind.should.be.exactly('return'); - }); - it('test if statements', function () { - var ast = parser.parseEval([ - 'if /* ignore */ (/* */ true) /* ignore */ {', - '# inner statement', - '} /* ignore */ else /* ignore */ ', - // else with a inner if single statement : - ' if (true /* ignore */) /* ignore */ {', - ' } /* ignore */ elseif /* ignore */ (/* ignore */ false /* ignore */ /* ignore */) /* ignore */ /* ignore */ {', - ' } /* ignore */ else /* ignore */ {', - ' }', - 'if (false) /* ignore */ : /* ignore */', - '/* ignore */ endif /* ignore */;/* ignore */' - ].join('\n'), { - lexer: { - //debug: true - }, - parser: { - extractDoc: true, - // debug: true - } - }); - ast.children.length.should.be.exactly(3); - ast.children[0].kind.should.be.exactly('if'); - ast.children[1].kind.should.be.exactly('if'); - ast.children[2].kind.should.be.exactly('doc'); - }); - it('test try statements', function () { - var ast = parser.parseEval([ - 'try /* ignore */ {', - '# inner statement', - '} /* dd */ catch(/* zz */ \\Exception /* 1 */ | /* 2 */ \\Foo /* aa */ $e /* bb */) /* dd */ {', - '/* ee */', - '} /* zz */ finally /* yy */ {', - '/* ignore */', - '} // end' - ].join('\n'), { - lexer: { - //debug: true - }, - parser: { - extractDoc: true, - // debug: true - } - }); - ast.children.length.should.be.exactly(2); - ast.children[0].kind.should.be.exactly('try'); - ast.children[0].body.kind.should.be.exactly('block'); - ast.children[0].catches[0].kind.should.be.exactly('catch'); - ast.children[0].catches[0].what[0].name.should.be.exactly('\\Exception'); - ast.children[0].catches[0].what[1].name.should.be.exactly('\\Foo'); - ast.children[0].catches[0].variable.name.should.be.exactly('e'); - ast.children[1].kind.should.be.exactly('doc'); - }); - }); - - describe('test classes', function () { - var ast = parser.parseEval([ - '/**', - ' * Description', - ' */', - 'class /* ignore */ name /* hehe */ {', - ' // @var test', - ' protected $test, $toto;', - ' // ignored comment', - ' /** @var Class */', - ' static public $foo = 123;', - ' /** ignored also **/', - ' /**', - ' * @return void', - ' */', - ' public function void() { }', - '}' - ].join('\n'), { - parser: { - extractDoc: true - } - }); - it('assume doc block before class', function () { - ast.children[0].kind.should.be.exactly("doc"); - ast.children[1].kind.should.be.exactly("class"); - }); - it('test class elements', function () { - var body = ast.children[1].body; - - body[0].kind.should.be.exactly("doc"); - body[0].lines[0].should.be.exactly("@var test"); - - body[1].kind.should.be.exactly("property"); - body[1].name.should.be.exactly("test"); - - body[2].kind.should.be.exactly("property"); - body[2].name.should.be.exactly("toto"); - - body[3].kind.should.be.exactly("doc"); - body[3].lines[0].should.be.exactly("ignored comment"); - - body[4].kind.should.be.exactly("doc"); - body[4].lines[0].should.be.exactly("@var Class"); - - body[5].kind.should.be.exactly("property"); - body[5].name.should.be.exactly("foo"); - - body[8].kind.should.be.exactly("method"); - body[8].name.should.be.exactly("void"); - }); - }); - -}); diff --git a/test/debug.js b/test/debug.js new file mode 100644 index 000000000..27d30f754 --- /dev/null +++ b/test/debug.js @@ -0,0 +1,39 @@ +/** +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "program": "${workspaceFolder}/test/debug.js" + } + ] +} + */ +const util = require("util"); +const parser = require("../src/index"); +const ast = parser.parseCode( + ` + 123; +} +`, + { + parser: { + debug: true, + extractDoc: true, + }, + ast: { + withPositions: true, + withSource: true, + }, + }, +); +console.log(util.inspect(ast, false, 10, true)); diff --git a/test/exprTests.js b/test/exprTests.js deleted file mode 100644 index 9f3a0aee0..000000000 --- a/test/exprTests.js +++ /dev/null @@ -1,317 +0,0 @@ -var should = require("should"); -var parser = require('../src/index'); - -describe('Test expressions', function() { - it('test binary', function() { - var ast = parser.parseEval([ - '1 | 3;', - '1 & 3;', - '1 ^ 3;', - '"1" . "3";', - '1 + 3;', - '1 - 3;', - '1 * 3;', - '1 / 3;', - '1 % 3;', - '1 ** 3;', - '1 << 3;', - '1 >> 3;' - ].join('\n')); - - ast.children.should.matchEach(function (node) { - node.should.have.property('kind', 'bin'); - node.left.value.should.be.exactly('1'); - node.right.value.should.be.exactly('3'); - }); - - ast.children.map(function (node) { return node.type; }) - .should.deepEqual([ - '|', '&', '^', '.', '+', '-', '*', '/', '%', '**', '<<', '>>' - ]); - }); - - it('test more binary ops (formerly bool)', function() { - var ast = parser.parseEval([ - '$a && $b;', - '$a AND $b;', - '$a || $b;', - '$a OR $b;', - '$a XOR $b;', - '$a === $b;', - '$a !== $b;', - '$a == $b;', - '$a != $b;', - '$a > $b;', - '$a < $b;', - '$a >= $b;', - '$a <= $b;', - '$a <=> $b;', - '$a instanceof $b;' - ].join('\n')); - - ast.children.should.matchEach(function (node) { - node.should.have.property('kind', 'bin'); - node.left.name.should.be.exactly('a'); - node.right.name.should.be.exactly('b'); - }); - - ast.children.map(function (node) { return node.type; }) - .should.deepEqual([ - '&&', 'and', '||', 'or', 'xor', '===', '!==', '==', '!=', '>', '<', '>=', '<=', '<=>', 'instanceof' - ]); - }); - - - it('test assignements', function() { - var ast = parser.parseEval([ - '$a = $b;', - '$a .= $b;', - '$a += $b;', - '$a -= $b;', - '$a *= $b;', - '$a **= $b;', - '$a /= $b;', - '$a &= $b;', - '$a |= $b;', - '$a %= $b;', - '$a ^= $b;', - '$a <<= $b;', - '$a >>= $b;' - ].join('\n')); - // @todo - }); - - it('test if based returns', function() { - var ast = parser.parseEval([ - '$a ?? false;', - '$a > 5 ? true : false;', - '$a ?: false;' - ].join('\n')); - //console.log(ast.children[1]); - ast.children[1].kind.should.be.exactly('retif'); - - }); - - it('test silent', function() { - var ast = parser.parseEval([ - '@trigger_error();' - ].join('\n')); - ast.children[0].kind.should.be.exactly('silent'); - ast.children[0].expr.kind.should.be.exactly('call'); - }); - - it('test generators', function() { - var ast = parser.parseEval([ - 'function gen() {', - ' yield 0; // key 0', - ' yield from foo(); // keys 0-2', - ' yield 1 => $a; // key 1', - '}' - ].join('\n')); - var expr = ast.children[0].body.children; - expr[0].kind.should.be.exactly('yield'); - expr[0].value.kind.should.be.exactly('number'); - - expr[1].kind.should.be.exactly('yieldfrom'); - expr[1].value.kind.should.be.exactly('call'); - - expr[2].kind.should.be.exactly('yield'); - expr[2].key.kind.should.be.exactly('number'); - expr[2].value.kind.should.be.exactly('variable'); - }); - - it('test unary', function() { - var ast = parser.parseEval([ - '+$var;', - '~$var;', - '!$var;', - '-$var;' - ].join('\n')); - ast.children[0].kind.should.be.exactly('unary'); - ast.children[0].type.should.be.exactly('+'); - ast.children[0].what.kind.should.be.exactly('variable'); - ast.children[1].kind.should.be.exactly('unary'); - ast.children[1].type.should.be.exactly('~'); - ast.children[1].what.kind.should.be.exactly('variable'); - ast.children[2].kind.should.be.exactly('unary'); - ast.children[2].type.should.be.exactly('!'); - ast.children[2].what.kind.should.be.exactly('variable'); - ast.children[3].kind.should.be.exactly('unary'); - ast.children[3].type.should.be.exactly('-'); - ast.children[3].what.kind.should.be.exactly('variable'); - }); - - it('test cast', function() { - var ast = parser.parseEval([ - '(int)$var;', - '(double)$var;', - '(string)$var;', - '(array)$var;', - '(object)$var;', - '(boolean)$var;', - '(unset)$var;' - ].join('\n')); - ast.children[0].kind.should.be.exactly('cast'); - ast.children[0].type.should.be.exactly('int'); - ast.children[1].kind.should.be.exactly('cast'); - ast.children[1].type.should.be.exactly('double'); - ast.children[2].kind.should.be.exactly('cast'); - ast.children[2].type.should.be.exactly('string'); - ast.children[3].kind.should.be.exactly('cast'); - ast.children[3].type.should.be.exactly('array'); - ast.children[4].kind.should.be.exactly('cast'); - ast.children[4].type.should.be.exactly('object'); - ast.children[5].kind.should.be.exactly('cast'); - ast.children[5].type.should.be.exactly('boolean'); - ast.children[6].kind.should.be.exactly('unset'); - }); - - it('test exit', function() { - var ast = parser.parseEval([ - 'exit(1);', - 'die();', - 'exit;' - ].join('\n')); - ast.children[0].kind.should.be.exactly('exit'); - ast.children[1].kind.should.be.exactly('exit'); - ast.children[2].kind.should.be.exactly('exit'); - }); - - it('test list statements', function() { - var ast = parser.parseEval([ - 'list($a => list($c,$d,,$e,), $b) = [1, 2];' - ].join('\n'), { - ast: { - withPositions: true - } - }); - // @todo - }); - - it('test incr/decr', function() { - var ast = parser.parseEval([ - '$i++;', - '$i--;', - '++$i;', - '--$i;' - ].join('\n'), { - ast: { - withPositions: true - } - }); - ast.children[0].kind.should.be.exactly('post'); - ast.children[1].kind.should.be.exactly('post'); - ast.children[2].kind.should.be.exactly('pre'); - ast.children[3].kind.should.be.exactly('pre'); - ast.children[0].type.should.be.exactly('+'); - ast.children[1].type.should.be.exactly('-'); - ast.children[2].type.should.be.exactly('+'); - ast.children[3].type.should.be.exactly('-'); - }); - - it('should fail to assign constants', function() { - var ast = parser.parseEval('a = 1;', { - parser: { debug: false, suppressErrors: true } - }); - var msg = 'Parse Error : syntax error, unexpected \'=\' on line 1'; - ast.errors.length.should.be.exactly(1); - ast.errors[0].message.should.be.exactly(msg); - }); - - it('should fail to assign class constants', function() { - var ast = parser.parseEval('foo::b = 1;', { - parser: { debug: false, suppressErrors: true } - }); - var msg = 'Parse Error : syntax error, unexpected \'=\' on line 1'; - ast.errors.length.should.be.exactly(1); - ast.errors[0].message.should.be.exactly(msg); - }); - - it('should assign class static', function() { - var ast = parser.parseEval('a::$b = 1;', { - parser: { debug: false, suppressErrors: true } - }); - ast.errors.length.should.be.exactly(0); - ast.children[0].kind.should.be.exactly('assign'); - }); - - it('test new', function() { - var ast = parser.parseEval([ - '$a = new \\foo();', - '$a = new namespace\\foo::class();', - '$a = new $foo();', - '$a = new class extends foo implements bar { };', - ].join('\n'), { - parser: { debug: false } - }); - ast.children[0].right.kind.should.be.exactly('new'); - ast.children[0].right.what.kind.should.be.exactly('identifier'); - - ast.children[2].right.kind.should.be.exactly('new'); - ast.children[2].right.what.kind.should.be.exactly('variable'); - - ast.children[3].right.kind.should.be.exactly('new'); - ast.children[3].right.what.kind.should.be.exactly('class'); - }); - - it('test nested expressions precedence', function() { - var ast = parser.parseEval([ - '$a = 5 * 2 + 1;', // same as ((5 * 2) + 1) - '$b = 5 * (2 + 1);', - '$c = 1 + 2 / 3 + 4;', // same as (1 + ((2 / 3) + 4)) - '$d = 1 !== 2 && 3;', // same as (1 !== 2) && 3 - ].join('\n'), { - parser: { debug: false } - }); - var aExpr = ast.children[0].right; - aExpr.kind.should.be.exactly('bin'); - aExpr.right.value.should.be.exactly('1'); - aExpr.type.should.be.exactly('+'); - - aExpr.left.left.value.should.be.exactly('5'); - aExpr.left.type.should.be.exactly('*'); - aExpr.left.right.value.should.be.exactly('2'); - - var bExpr = ast.children[1].right; - bExpr.kind.should.be.exactly('bin'); - bExpr.left.value.should.be.exactly('5'); - bExpr.type.should.be.exactly('*'); - - bExpr.right.kind.should.be.exactly('parenthesis'); - bExpr.right.inner.left.value.should.be.exactly('2'); - bExpr.right.inner.type.should.be.exactly('+'); - bExpr.right.inner.right.value.should.be.exactly('1'); - - var cExpr = ast.children[2].right; - cExpr.kind.should.be.exactly('bin'); - cExpr.left.type.should.be.exactly('+'); - cExpr.left.left.value.should.be.exactly('1'); - cExpr.left.right.type.should.be.exactly('/'); - cExpr.type.should.be.exactly('+'); - cExpr.right.value.should.be.exactly('4'); - - var dExpr = ast.children[3].right; - dExpr.should.have.property('kind', 'bin'); - JSON.parse(JSON.stringify(dExpr)).should.deepEqual({ - kind: "bin", - left: { - kind: "bin", - left: { - kind: "number", - value: "1" - }, - right: { - kind: "number", - value: "2" - }, - type: "!==" - }, - right: { - kind: "number", - value: "3" - }, - type: "&&" - }); - }); - -}); diff --git a/test/functionTests.js b/test/functionTests.js deleted file mode 100644 index 45dc0306b..000000000 --- a/test/functionTests.js +++ /dev/null @@ -1,94 +0,0 @@ -var should = require("should"); -var parser = require('../src/index'); - -describe('Function tests', function() { - var ast = parser.parseEval([ - 'function &foo($a = 1, callable $b, ?array &...$params) : ?boolean {}', - '$a = function &($b) use(&$c, $d) : array {', - ' return true;', - '};', - '$b = foo(...[1, null, 1, 2, 3]);' - ].join('\n')); - - - it('test variadic error', function () { - var astErr = parser.parseEval([ - '$b = foo(...[1, 2, 3], $a);' - ].join('\n'), { - parser: { - suppressErrors: true - } - }); - var msg = 'Unexpected argument after a variadic argument on line 1'; - astErr.errors.length.should.be.exactly(1); - astErr.errors[0].line.should.be.exactly(1); - astErr.errors[0].message.should.be.exactly(msg); - }); - - it('test description', function () { - // Get result from parser - ast.children[0].kind.should.be.exactly('function'); - ast.children[0].name.should.be.exactly('foo'); - ast.children[0].byref.should.be.exactly(true); - ast.children[0].nullable.should.be.exactly(true); - ast.children[0].type.name.should.be.exactly('boolean'); - }); - - it('test arguments', function () { - /* - // 1st param - var arg1 = args[0]; - arg1[0].should.be.exactly('param'); - arg1[1].should.be.exactly('$a'); - should.equal(arg1[2], null); - arg1[3][0].should.be.exactly('number'); - arg1[3][1].should.be.exactly('1'); - arg1[4].should.be.exactly(false, 'not byref'); - arg1[5].should.be.exactly(false, 'not variadic'); - - // 2nd param - var arg2 = args[1]; - arg2[0].should.be.exactly('param'); - arg2[1].should.be.exactly('$params'); - arg2[2][0].should.be.exactly('array'); - should.equal(arg2[3], null); - arg2[4].should.be.exactly(true, 'byref'); - arg2[5].should.be.exactly(true, 'variadic'); - */ - }); - - it('test closure', function () { - var fn = ast.children[1].right; - fn.kind.should.be.exactly('closure'); - fn.byref.should.be.exactly(true); - fn.uses.length.should.be.exactly(2); - fn.uses[0].kind.should.be.exactly('variable'); - fn.uses[0].name.should.be.exactly('c'); - fn.uses[0].byref.should.be.exactly(true); - fn.uses[1].kind.should.be.exactly('variable'); - fn.uses[1].name.should.be.exactly('d'); - fn.uses[1].byref.should.be.exactly(false); - fn.arguments.length.should.be.exactly(1); - fn.arguments[0].kind.should.be.exactly('parameter'); - fn.arguments[0].name.should.be.exactly('b'); - fn.arguments[0].byref.should.be.exactly(false); - fn.type.kind.should.be.exactly('identifier'); - fn.type.name.should.be.exactly('\\array'); - fn.nullable.should.be.exactly(false); - fn.body.kind.should.be.exactly('block'); - }); - - it('test static closure', function() { - // from expr - var ast = parser.parseEval('$a = static function() {};'); - var fn = ast.children[0].right; - fn.kind.should.be.exactly('closure'); - fn.isStatic.should.be.exactly(true); - // from statement - ast = parser.parseEval('static function() {};'); - fn = ast.children[0]; - fn.kind.should.be.exactly('closure'); - fn.isStatic.should.be.exactly(true); - }); - -}); diff --git a/test/gracefulTests.js b/test/gracefulTests.js deleted file mode 100644 index 1e3e20b6a..000000000 --- a/test/gracefulTests.js +++ /dev/null @@ -1,104 +0,0 @@ -var should = require("should"); -var parser = require('../src/index'); - -describe('Test graceful mode', function() { - - describe('to suppress errors', function() { - - // init a new parser instance - var test = parser.create({ - parser: { - suppressErrors: true - } - }); - - it('should contain 2 errors', function () { - // Get result from parser - var ast = test.parseEval([ - '$var = ', // 1. - 'function() {', // 2. - '$foo = ', // 3. <-- missing expr - '}', // 4. - '}' // 5. <-- extra '}' token here - ].join('\n')); - ast.errors.length.should.be.exactly(2); - // @todo ast[1][0][2][5][0][2][0].should.be.exactly('error'); - }); - - it('test expr', function () { - var ast = test.parseEval('$a = $b -; $foo = $a;'); - - ast.errors.length.should.be.exactly(2); - ast.children.length.should.be.exactly(2); - - /** @todo - ast[1][0][2][0].should.be.exactly('bin'); - ast[1][0][2][1].should.be.exactly('-'); - ast[1][0][2][3][0].should.be.exactly('error'); - - ast[1][1][0].should.be.exactly('set'); - ast[1][1][1][0].should.be.exactly('var'); - ast[1][1][1][1].should.be.exactly('$foo'); - */ - }); - - it('test class', function () { - var ast = test.parseEval('class foo { foo const A = 1 '); - - ast.errors.length.should.be.exactly(3); - ast.children.length.should.be.exactly(1); - - /** @todo - ast[1][0][0].should.be.exactly('class'); - ast[1][0][1].should.be.exactly('foo'); - ast[1][0][5].length.should.be.exactly(2); // including the foo error - ast[1][0][5][0][0].should.be.exactly('error'); - ast[1][0][5][1][0].should.be.exactly('const'); - ast[1][0][5][1][1].should.be.exactly('A'); - ast[1][0][5][1][2][1].should.be.exactly('1'); - */ - - }); - - it('test flags', function () { - var ast = test.parseEval([ - 'final final interface foo {', - ' abstract function func() ' - ].join('\n')); - ast.errors.length.should.be.exactly(4); - ast.children.length.should.be.exactly(1); - ast.children[0].kind.should.be.exactly('interface'); - }); - - it('test function arguments', function () { - // test.parser.debug = true; - var ast = test.parseEval([ - '$foo->bar($arg, );', - '$foo = new bar($baz, ,$foo);' - ].join('\n')); - var callNode = ast.children[0]; - callNode.kind.should.be.exactly('call'); - callNode.what.kind.should.be.exactly('propertylookup'); - callNode.arguments.length.should.be.exactly(1); - callNode.arguments[0].name.should.be.exactly('arg'); - var assignNode = ast.children[1]; - assignNode.kind.should.be.exactly('assign'); - assignNode.right.kind.should.be.exactly('new'); - assignNode.right.arguments[0].name.should.be.exactly('baz'); - // the supressError mode cant guarantee $foo to be included into the arguments list - }); - - it('test method chains', function () { - // test.parser.debug = true; - var ast = test.parseEval([ - '$controller->expects($this->once())', - '->' - ].join('\n')); - ast.children[0].kind.should.be.exactly('propertylookup'); - ast.children[0].what.kind.should.be.exactly('call'); - ast.children[0].what.what.kind.should.be.exactly('propertylookup'); - }); - - }); - -}); diff --git a/test/ifTests.js b/test/ifTests.js deleted file mode 100644 index ccda96f78..000000000 --- a/test/ifTests.js +++ /dev/null @@ -1,105 +0,0 @@ -var should = require("should"); -var parser = require('../src/index'); - -describe('Test IF statements', function() { - describe('Test common cases', function() { - var ast = parser.parseEval([ - 'if (true) {', - ' echo "is true";', - '} else if (false) {', - ' echo "false";', - '} elseif (false) {', - ' echo "2nd";', - '} else {', - ' echo "else";', - '}' - ].join('\n'), { - parser: { debug: false } - }); - it('test if structure', function() { - ast.children.length.should.be.exactly(1); - ast.children[0].kind.should.be.exactly('if'); - ast.children[0].shortForm.should.be.exactly(false); - ast.children[0].test.kind.should.be.exactly('boolean'); - ast.children[0].test.value.should.be.exactly(true); - ast.children[0].body.children.length.should.be.exactly(1); - ast.children[0].body.children[0].kind.should.be.exactly('echo'); - }); - it('test else branches', function() { - var el1 = ast.children[0].alternate; - el1.kind.should.be.exactly('if'); - el1.test.kind.should.be.exactly('boolean'); - el1.test.value.should.be.exactly(false); - el1.body.children[0].kind.should.be.exactly('echo'); - el1.body.children[0].arguments[0].value.should.be.exactly('false'); - - var el2 = el1.alternate; - el2.kind.should.be.exactly('if'); - el2.body.children[0].kind.should.be.exactly('echo'); - el2.body.children[0].arguments[0].value.should.be.exactly('2nd'); - - var el3 = el2.alternate; - el3.kind.should.be.exactly('block'); - el3.children[0].kind.should.be.exactly('echo'); - el3.children[0].arguments[0].value.should.be.exactly('else'); - }); - }); - describe('Test short form', function() { - var ast = parser.parseEval([ - 'if (true):', - ' echo "is true";', - 'elseif (false):', - ' echo "false";', - 'else:', - ' echo "else";', - 'endif;' - ].join('\n'), { - parser: { debug: false } - }); - it('should be shortForm flagged', function() { - ast.children.length.should.be.exactly(1); - ast.children[0].kind.should.be.exactly('if'); - ast.children[0].shortForm.should.be.exactly(true); - }); - it('test else branches', function() { - var el1 = ast.children[0].alternate; - el1.shortForm.should.be.exactly(true); - var el2 = el1.alternate; - el2.kind.should.be.exactly('block'); - }); - }); - describe('Improve coverage', function() { - var ast = parser.parseEval([ - 'if (true):', - ' echo "is true";', - 'elseif (false):', - ' echo "false";', - 'elseif (false):', - ' echo "false";', - 'endif;', - 'if (true):', - ' echo "is true";', - 'else:', - ' echo "false";', - 'endif;' - ].join('\n'), { - parser: { debug: false } - }); - it('should have 2 childs', function() { - ast.children.length.should.be.exactly(2); - ast.children[0].kind.should.be.exactly('if'); - ast.children[0].shortForm.should.be.exactly(true); - ast.children[1].kind.should.be.exactly('if'); - ast.children[1].shortForm.should.be.exactly(true); - }); - it('test else branches', function() { - var el1 = ast.children[0].alternate; - el1.kind.should.be.exactly('if'); - var el2 = el1.alternate; - el2.kind.should.be.exactly('if'); - should.equal(el2.alternate, null); // no else - // else block - ast.children[1].alternate.kind.should.be.exactly('block'); - }); - }); -}); diff --git a/test/lexerTests.js b/test/lexerTests.js deleted file mode 100644 index 29e76898f..000000000 --- a/test/lexerTests.js +++ /dev/null @@ -1,84 +0,0 @@ -var should = require("should"); -var parser = require('./main'); - -describe('Test lexer', function() { - describe('initial state', function() { - var ast = parser.parseCode([ - '', - '', - '<% echo $b; %>', - '<%= $b %>' - ].join('\n'), { - lexer: { - short_tags: true, - asp_tags: true - } - }); - it('parse short tag', function() { - ast.children[0].kind.should.be.exactly('echo'); - ast.children[0].arguments[0].kind.should.be.exactly('variable'); - ast.children[0].arguments[0].name.should.be.exactly('a'); - }); - it('parse short echo', function() { - ast.children[1].kind.should.be.exactly('echo'); - ast.children[1].arguments[0].kind.should.be.exactly('variable'); - ast.children[1].arguments[0].name.should.be.exactly('a'); - }); - it('parse asp tag', function() { - ast.children[2].kind.should.be.exactly('echo'); - ast.children[2].arguments[0].kind.should.be.exactly('variable'); - ast.children[2].arguments[0].name.should.be.exactly('b'); - }); - it('parse asp echo tag', function() { - ast.children[3].kind.should.be.exactly('echo'); - ast.children[3].arguments[0].kind.should.be.exactly('variable'); - ast.children[3].arguments[0].name.should.be.exactly('b'); - }); - }); - - describe('test comments', function() { - it('should work ^^', function() { - var ast = parser.parseCode([ - '', - '<%', - ' // another line %>', - '', - ' $v\n";', - 'foreach([[1,2], [3,4]] as list($a, $b) => [$c, $d]):', - 'echo "$a -> $b\n";', - 'endforeach;' - ].join('\n'), { - parser: { debug: false } - }); - it('test kind & form', function() { - ast.children[0].kind.should.be.exactly('foreach'); - ast.children[0].shortForm.should.be.exactly(false); - ast.children[1].kind.should.be.exactly('foreach'); - ast.children[1].shortForm.should.be.exactly(true); - - }); - it('test source', function() { - ast.children[0].source.kind.should.be.exactly('variable'); - ast.children[0].source.byref.should.be.exactly(true); - ast.children[0].source.name.should.be.exactly('foo'); - ast.children[1].source.kind.should.be.exactly('array'); - ast.children[1].source.items.length.should.be.exactly(2); - }); - it('test key', function() { - should.equal(ast.children[0].key, null); - ast.children[1].key.kind.should.be.exactly('list'); - ast.children[1].key.arguments.length.should.be.exactly(2); - }); - it('test value', function() { - ast.children[0].value.kind.should.be.exactly('variable'); - ast.children[0].value.name.should.be.exactly('v'); - ast.children[1].value.kind.should.be.exactly('array'); - ast.children[1].value.shortForm.should.be.exactly(true); - }); - it('test body', function() { - ast.children[0].body.kind.should.be.exactly('echo'); - ast.children[1].body.kind.should.be.exactly('block'); - ast.children[1].body.children[0].kind.should.be.exactly('echo'); - }); - }); - -}); diff --git a/test/main.js b/test/main.js index 9d7b5790c..b5098f7b8 100644 --- a/test/main.js +++ b/test/main.js @@ -5,7 +5,7 @@ * @url http://glayzzle.com */ -var parser = require('../src/index'); +const parser = require("../src/index"); // @todo : move here the debug code // @todo : add an automated token check (with php7) module.exports = parser; diff --git a/test/namespaceTest.js b/test/namespaceTest.js deleted file mode 100644 index b3455dbd9..000000000 --- a/test/namespaceTest.js +++ /dev/null @@ -1,98 +0,0 @@ -var should = require("should"); -var parser = require('../src/index'); - -describe('Test namespace statements', function() { - - var singleNs = parser.parseEval([ - 'namespace foo;', - ' use bar\\baz as barBaz;', - ' use const bar\\baz as barBaz, baz\\boo as bazBoo;', - ' use function bar\\baz as barBaz, baz\\boo as bazBoo;', - ' use bar\\baz {', - ' const FOO as BAZ_FOO,', - ' function BOO as BAZ_BOO', - ' };', - ' use const azerty {', - ' A as AZERTY_A,', - ' B as AZERTY_B', - ' };', - // relative namespace - ' $a = namespace\\barBaz;', - // fully qualified - ' $b = \\barBaz;', - // qualified - ' $c = barBaz\\foo;', - // unqualified - ' $d = barBaz;' - ].join('\n'), { - parser: { debug: false } - }); - - var multiNs = parser.parseEval([ - 'namespace \\foo {', - ' $i++;', - '}', - 'namespace {', - ' $b++;', - '}' - ].join('\n'), { - parser: { debug: false } - }); - - var nsKeyword = parser.parseEval([ - 'namespace\\foo();', - '$var = namespace\\bar;', - ].join('\n'), { - parser: { debug: false } - }); - - var nsError = parser.parseEval([ - 'namespace $var = true;', - ].join('\n'), { - parser: { debug: false, suppressErrors: true } - }); - - it('check namespace', function() { - // @todo - }); - - it('check use', function() { - // @todo - }); - - it('check resolution', function() { - // @todo - }); - - it('check silent mode', function() { - nsError.errors.length.should.be.exactly(2); - nsError.errors[0].line.should.be.exactly(1); - nsError.errors[1].line.should.be.exactly(1); - nsError.children[0].kind.should.be.exactly('namespace'); - nsError.children[0].name.name.should.be.exactly(''); - nsError.children[0].children[0].kind.should.be.exactly('assign'); - nsError.children[0].children[0].left.kind.should.be.exactly('variable'); - nsError.children[0].children[0].right.kind.should.be.exactly('boolean'); - }); - - it('check namespace keyword', function() { - nsKeyword.children[0].kind.should.be.exactly('call'); - nsKeyword.children[0].what.kind.should.be.exactly('identifier'); - nsKeyword.children[0].what.resolution.should.be.exactly('rn'); - nsKeyword.children[0].what.name.should.be.exactly('foo'); - // @todo : test second child - }); - - it('should work with declare statement', function() { - var ast = parser.parseEval([ - 'declare(strict_types=1);', - 'namespace foo;', - 'class bar {}' - ].join('\n'), { - parser: { - debug: false - } - }); - // @todo : make assertions - }); -}); diff --git a/test/numberTests.js b/test/numberTests.js deleted file mode 100644 index 795177901..000000000 --- a/test/numberTests.js +++ /dev/null @@ -1,41 +0,0 @@ -var should = require("should"); -var parser = require('./main'); - -describe('Test numbers', function() { - - describe('comon tests', function() { - var ast = parser.parseEval([ - '$a = -1.5;', - '$b = 1234;', - '$c = 9223372036854775807;', - '$c = 9223372036854775808;', - '$d = 0x1A;', - '$d = 0xFF;', - '$e = 0b1011;', - '$f = 0123;', - '$g = 1.2e3;', - '$h = 7E-10;' - ].join('\n')); - it('should be float', function() { - ast.children[0].right.kind.should.be.exactly('number'); - ast.children[0].right.value.should.be.exactly('-1.5'); - }); - - }); - // @fixme should test bad syntaxes - // like 01239 (octal number with bad token) - describe('edge tests', function() { - var ast = parser.parseEval([ - '$a = 0xx;', - '$b = 0b2;', - '$c = 01239;', - '$d = 7E-a;', - '$e = 7EX;' - ].join('\n'), { - parser: { - suppressErrors: true - } - }); - - }); -}); diff --git a/test/precedence.js b/test/precedence.js deleted file mode 100644 index 4655fbf2c..000000000 --- a/test/precedence.js +++ /dev/null @@ -1,142 +0,0 @@ -var should = require("should"); -var parser = require('../src/index'); - -/** - * Check precedence by using parenthesis on node B - */ -var checkPrecedence = function(a, b) { - if (!a || !b) return false; - if (b.kind === 'parenthesis') { - // force the precendence with parenthesis - // ignore them in test - b = b.inner; - } - for(var k in b) { - if (b.hasOwnProperty(k)) { - if (!a.hasOwnProperty(k)) return false; - if (typeof b[k] === 'object') { - checkPrecedence(a[k], b[k]); - } else { - a[k].should.be.equal(b[k]); - } - } - } - return true; -}; - -var shouldBeSame = function(a, b) { - var ast = parser.parseEval([ - a + ';', - b + ';' - ].join('\n')); - checkPrecedence(ast.children[0], ast.children[1]).should.be.true(); -}; - -// START TESTS HERE -describe('Test precedence', function() { - it('test *', function() { - shouldBeSame('5 * 3 - 2', '(5 * 3) - 2'); - shouldBeSame('2 - 5 * 3', '2 - (5 * 3)'); - }); - it('test /', function() { - shouldBeSame('5 / 3 + 2', '(5 / 3) + 2'); - shouldBeSame('5 + 3 / 2', '5 + (3 / 2)'); - }); - it('test %', function() { - shouldBeSame('5 % 3 . 2', '(5 % 3) . 2'); - }); - it('test instanceof', function() { - shouldBeSame('3 instanceof 2 * 5', '(3 instanceof 2) * 5'); - }); - it('test <<', function() { - shouldBeSame('1 + 3 << 5', '(1 + 3) << 5'); - }); - it('test ==', function() { - shouldBeSame('1 + 5 == 3', '(1 + 5 ) == 3'); - }); - it('test &', function() { - shouldBeSame('1 == 2 & 3', '(1 == 2) & 3'); - }); - it('test ^', function() { - shouldBeSame('1 & 2 ^ 3', '(1 & 2) ^ 3'); - }); - it('test |', function() { - shouldBeSame('1 ^ 2 | 3', '(1 ^ 2) | 3;'); - }); - it('test &&', function() { - var ast = parser.parseEval([ - '1 | 2 && 3;', - '(1 | 2) && 3;' - ].join('\n')); - checkPrecedence(ast.children[0],ast.children[1]).should.be.true(); - }); - it('test ||', function() { - var ast = parser.parseEval([ - '1 && 2 || 3;', - '(1 && 2) || 3;' - ].join('\n')); - checkPrecedence(ast.children[0], ast.children[1]).should.be.true(); - }); - it('test ??', function() { - var ast = parser.parseEval([ - '1 || 2 ?? 3;', - '(1 || 2) ?? 3;' - ].join('\n')); - checkPrecedence(ast.children[0], ast.children[1]).should.be.true(); - }); - it('test ?:', function() { - shouldBeSame('1 ?? 2 ? 3 : 5', '(1 ?? 2) ? 3 : 5'); - shouldBeSame('1 and 2 ? 3 : 5', '1 and (2 ? 3 : 5)'); - }); - it('test =', function() { - shouldBeSame('5 + $a = 1', '5 + ($a = 1)'); - shouldBeSame('5 XOR $a += 1', '5 XOR ($a += 1)'); - }); - it('test OR', function() { - shouldBeSame('5 XOR 4 OR 3', '(5 XOR 4) OR 3'); - shouldBeSame('5 OR 4 XOR 3', '5 OR (4 XOR 3)'); - }); - it('test XOR', function() { - shouldBeSame('5 AND 4 XOR 3', '(5 AND 4) XOR 3'); - shouldBeSame('5 XOR 4 AND 3', '5 XOR (4 AND 3)'); - }); - it('test AND', function() { - shouldBeSame('5 + 4 AND 3', '(5 + 4) AND 3'); - shouldBeSame('5 AND 4 + 3', '5 AND (4 + 3)'); - }); - it('test unary : !', function() { - shouldBeSame('!4 instanceof 3', '(!4) instanceof 3'); - shouldBeSame('!4 + 5 instanceof 3', '(!4) + (5 instanceof 3)'); - shouldBeSame('6 + !4 + 5', '6 + (!4) + 5'); - shouldBeSame('if($a && !$b) {}', 'if($a && (!$b)) {}'); - }); - it('test concat', function() { - shouldBeSame('"a"."b"."c"."d"', '((("a"."b")."c")."d")'); - }); - it('test retif', function() { - shouldBeSame('$a ? 1 : $b ? 2 : $c ? 3 : 4', '(($a ? 1 : $b) ? 2 : $c) ? 3 : 4'); - }); - it('test + / *', function() { - shouldBeSame('1 + 2 * 3', '1 + (2 * 3)'); - }); - // https://github.com/glayzzle/php-parser/issues/81 - it('test assign with and', function() { - shouldBeSame( - '$a and $b = $c and $d', - '($a and ($b = $c)) and $d' - ); - }); - it('test assign list', function() { - shouldBeSame( - '$a = $b = $c', - '($a = ($b = $c))' - ); - }); - it('test assign with &&', function() { - shouldBeSame( - '$a && $b = $c && $d', - '$a && ($b = ($c && $d))' - ); - }); - -}); diff --git a/test/precedence.test.js b/test/precedence.test.js new file mode 100644 index 000000000..50e60606e --- /dev/null +++ b/test/precedence.test.js @@ -0,0 +1,191 @@ +const parser = require("./main"); + +/** + * Check precedence by using parenthesis on node B + */ +function filterKey(fn, obj) { + if (Array.isArray(obj)) { + return obj.map((e) => filterKey(fn, e)); + } + + if (typeof obj === "object" && obj !== null) { + return Object.keys(obj) + .filter(fn) + .reduce( + (result, key) => ({ + ...result, + [key]: filterKey(fn, obj[key]), + }), + {}, + ); + } + + return obj; +} + +function shouldBeSame(a, b) { + const fn = (key) => key !== "parenthesizedExpression"; + expect(filterKey(fn, parser.parseEval(a))).toEqual( + filterKey(fn, parser.parseEval(b)), + ); +} + +// START TESTS HERE + +describe("Test infrastructure", function () { + it("should filter parenthesizedExpression prop", function () { + const fn = (key) => key !== "parenthesizedExpression"; + expect( + filterKey(fn, { foo: "bar", parenthesizedExpression: true }), + ).toEqual({ foo: "bar" }); + expect( + filterKey(fn, { x: { foo: "bar", parenthesizedExpression: true } }), + ).toEqual({ x: { foo: "bar" } }); + expect( + filterKey(fn, [{ foo: "bar", parenthesizedExpression: true }]), + ).toEqual([{ foo: "bar" }]); + }); +}); + +describe("Test precedence", function () { + it("test *", function () { + shouldBeSame("5 * 3 - 2", "(5 * 3) - 2"); + shouldBeSame("2 - 5 * 3", "2 - (5 * 3)"); + }); + it("test /", function () { + shouldBeSame("5 / 3 + 2", "(5 / 3) + 2"); + shouldBeSame("5 + 3 / 2", "5 + (3 / 2)"); + }); + it("test %", function () { + shouldBeSame("5 % 3 . 2", "(5 % 3) . 2"); + }); + it("test instanceof", function () { + shouldBeSame("$a instanceof $b && $c", "($a instanceof $b) && $c"); + }); + it("test <<", function () { + shouldBeSame("1 + 3 << 5", "(1 + 3) << 5"); + }); + it("test ==", function () { + shouldBeSame("1 + 5 == 3", "(1 + 5 ) == 3"); + }); + it("test &", function () { + shouldBeSame("1 == 2 & 3", "(1 == 2) & 3"); + }); + it("test ^", function () { + shouldBeSame("1 & 2 ^ 3", "(1 & 2) ^ 3"); + }); + it("test |", function () { + shouldBeSame("1 ^ 2 | 3", "(1 ^ 2) | 3"); + }); + it("test &&", function () { + shouldBeSame("1 | 2 && 3", "(1 | 2) && 3"); + }); + it("test ||", function () { + shouldBeSame("1 && 2 || 3", "(1 && 2) || 3"); + }); + it("test ??", function () { + shouldBeSame("1 || 2 ?? 3", "(1 || 2) ?? 3"); + }); + it("test ?? right-associative", function () { + shouldBeSame("1 ?? 2 ?? 3", "1 ?? (2 ?? 3)"); + }); + it("test ?? precedence", function () { + shouldBeSame("1 ?? 2 and 3", "(1 ?? 2) and 3"); + }); + it("test ** precedence", function () { + shouldBeSame("1 ** 2 + 3", "(1 ** 2) + 3"); + }); + it("test ** right-associative", function () { + shouldBeSame("1 ** 2 ** 3", "1 ** (2 ** 3)"); + }); + it("test ?:", function () { + shouldBeSame("1 ?? 2 ? 3 : 5", "(1 ?? 2) ? 3 : 5"); + shouldBeSame("1 and 2 ? 3 : 5", "1 and (2 ? 3 : 5)"); + }); + it("test =", function () { + shouldBeSame("5 + $a = 1", "5 + ($a = 1)"); + shouldBeSame("5 XOR $a += 1", "5 XOR ($a += 1)"); + }); + it("test OR", function () { + shouldBeSame("5 XOR 4 OR 3", "(5 XOR 4) OR 3"); + shouldBeSame("5 OR 4 XOR 3", "5 OR (4 XOR 3)"); + }); + it("test XOR", function () { + shouldBeSame("5 AND 4 XOR 3", "(5 AND 4) XOR 3"); + shouldBeSame("5 XOR 4 AND 3", "5 XOR (4 AND 3)"); + }); + it("test AND", function () { + shouldBeSame("5 + 4 AND 3", "(5 + 4) AND 3"); + shouldBeSame("5 AND 4 + 3", "5 AND (4 + 3)"); + }); + it("test unary : !", function () { + shouldBeSame("!$a instanceof $b", "(!$a) instanceof $b"); + shouldBeSame("!$a + $b instanceof $c", "(!$a) + ($b instanceof $c)"); + shouldBeSame("6 + !4 + 5", "6 + (!4) + 5"); + shouldBeSame("if($a && !$b) {}", "if($a && (!$b)) {}"); + }); + it("test concat", function () { + shouldBeSame('"a"."b"."c"."d"', '((("a"."b")."c")."d")'); + }); + it("test retif", function () { + shouldBeSame( + "$a ? 1 : $b ? 2 : $c ? 3 : 4", + "(($a ? 1 : $b) ? 2 : $c) ? 3 : 4", + ); + }); + it("test + / *", function () { + shouldBeSame("1 + 2 * 3", "1 + (2 * 3)"); + }); + // https://github.com/glayzzle/php-parser/issues/81 + it("test assign with and", function () { + shouldBeSame("$a and $b = $c and $d", "($a and ($b = $c)) and $d"); + }); + it("test assign list", function () { + shouldBeSame("$a = $b = $c", "($a = ($b = $c))"); + }); + it("test assign with &&", function () { + shouldBeSame("$a && $b = $c && $d", "$a && ($b = ($c && $d))"); + }); + it("test static lookup offsets", function () { + shouldBeSame("(Foo::$bar)['baz']();", "Foo::$bar['baz']();"); + }); + it("test silent node / bin", function () { + shouldBeSame("@foo() || @foo();", "(@foo()) || (@foo());"); + }); + it("test silent node / div", function () { + shouldBeSame("@$i / 0;", "@($i) / 0;"); + }); + it("test silent node / retif", function () { + shouldBeSame("@$var ? 1 : 2;", "(@$var) ? 1 : 2;"); + }); + it("test silent node / ret if", function () { + shouldBeSame( + "@$i == true ? @$foo : @$bar;", + "@($i) == true ? @($foo) : @($bar);", + ); + }); + it("test silent node - bugfix #355", function () { + shouldBeSame( + "echo 'pre' . (@$_GET['foo'] === 'bar' ? 'ok' : 'ko') . 'post'", + "echo 'pre' . (@($_GET['foo']) === 'bar' ? 'ok' : 'ko') . 'post'", + ); + }); + it("test silent node - bugfix #356", function () { + shouldBeSame("@$var += 10", "@($var += 10)"); + }); + it("test silent node / cast", function () { + shouldBeSame("@(int)$i + 1;", "@((int)$i) + 1;"); + }); + it("test silent node / property lookup", function () { + shouldBeSame("@$foo->bar;", "@($foo)->bar;"); + }); + it("test cast", function () { + shouldBeSame("$a = (string)$b . $c", "$a = ((string)$b) . $c"); + shouldBeSame("$a = (string)$b->foo . $c", "$a = ((string)$b->foo) . $c"); + shouldBeSame("(bool) $var ? 1 : 2;", "((bool)$var) ? 1 : 2;"); + }); + + it("test unary / retif", function () { + shouldBeSame("$a = +(+$var ? 1 : 2)", "$a = +((+$var) ? 1 : 2)"); + }); +}); diff --git a/test/scalarTests.js b/test/scalarTests.js deleted file mode 100644 index 27e6d2ded..000000000 --- a/test/scalarTests.js +++ /dev/null @@ -1,28 +0,0 @@ -var should = require("should"); -var parser = require('./main'); - -describe('Test scalar statements', function() { - it('constants', function() { - var ast = parser.parseEval([ - '$a = foo::ref[-5];' - ].join('\n'), { - parser: { - //debug: true - } - }); - // @todo assert console.log(ast); - }); - it('dereferencable', function() { - var ast = parser.parseEval([ - '$a = foo::bar()[5]->test;', - '$b = (new test())->foo();', - '$c = (foo())[5];', - '$d = (function($a) { return $a * 2; })(5);', - ].join('\n'), { - parser: { - // debug: true - } - }); - // @todo - }); -}); diff --git a/test/snapshot/__snapshots__/acid.test.js.snap b/test/snapshot/__snapshots__/acid.test.js.snap new file mode 100644 index 000000000..66955f4bb --- /dev/null +++ b/test/snapshot/__snapshots__/acid.test.js.snap @@ -0,0 +1,8665 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Acid level 1 1`] = ` +Program { + "children": [ + Inline { + "kind": "inline", + "loc": Location { + "end": Position { + "column": 0, + "line": 2, + "offset": 15, + }, + "source": "#!/usr/bin/php +", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "raw": "#!/usr/bin/php +", + "value": "#!/usr/bin/php +", + }, + Echo { + "expressions": [ + Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 17, + "line": 2, + "offset": 32, + }, + "source": "php_version()", + "start": Position { + "column": 4, + "line": 2, + "offset": 19, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 15, + "line": 2, + "offset": 30, + }, + "source": "php_version", + "start": Position { + "column": 4, + "line": 2, + "offset": 19, + }, + }, + "name": "php_version", + "resolution": "uqn", + }, + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 18, + "line": 2, + "offset": 33, + }, + "source": " 'achoum', + 'bashful' => 'tadah' + ]", + "start": Position { + "column": 14, + "line": 32, + "offset": 577, + }, + }, + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "loc": Location { + "end": Position { + "column": 5, + "line": 35, + "offset": 648, + }, + "source": "$dwarf = [ + 'sneezy' => 'achoum', + 'bashful' => 'tadah' + ]", + "start": Position { + "column": 14, + "line": 32, + "offset": 577, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 20, + "line": 32, + "offset": 583, + }, + "source": "$dwarf", + "start": Position { + "column": 14, + "line": 32, + "offset": 577, + }, + }, + "name": "dwarf", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 14, + "line": 33, + "offset": 602, + }, + "source": "'sneezy'", + "start": Position { + "column": 6, + "line": 33, + "offset": 594, + }, + }, + "raw": "'sneezy'", + "unicode": false, + "value": "sneezy", + }, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 26, + "line": 33, + "offset": 614, + }, + "source": "'sneezy' => 'achoum'", + "start": Position { + "column": 6, + "line": 33, + "offset": 594, + }, + }, + "unpack": false, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 26, + "line": 33, + "offset": 614, + }, + "source": "'achoum'", + "start": Position { + "column": 18, + "line": 33, + "offset": 606, + }, + }, + "raw": "'achoum'", + "unicode": false, + "value": "achoum", + }, + }, + Entry { + "byRef": false, + "key": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 15, + "line": 34, + "offset": 631, + }, + "source": "'bashful'", + "start": Position { + "column": 6, + "line": 34, + "offset": 622, + }, + }, + "raw": "'bashful'", + "unicode": false, + "value": "bashful", + }, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 26, + "line": 34, + "offset": 642, + }, + "source": "'bashful' => 'tadah'", + "start": Position { + "column": 6, + "line": 34, + "offset": 622, + }, + }, + "unpack": false, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 26, + "line": 34, + "offset": 642, + }, + "source": "'tadah'", + "start": Position { + "column": 19, + "line": 34, + "offset": 635, + }, + }, + "raw": "'tadah'", + "unicode": false, + "value": "tadah", + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 5, + "line": 35, + "offset": 648, + }, + "source": "[ + 'sneezy' => 'achoum', + 'bashful' => 'tadah' + ]", + "start": Position { + "column": 23, + "line": 32, + "offset": 586, + }, + }, + "shortForm": true, + }, + }, + ], + "visibility": "protected", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Foreach { + "body": Block { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "loc": Location { + "end": Position { + "column": 40, + "line": 42, + "offset": 855, + }, + "source": ""Hey ho $name, $greeting !"", + "start": Position { + "column": 13, + "line": 42, + "offset": 828, + }, + }, + "raw": ""Hey ho $name, $greeting !"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 21, + "line": 42, + "offset": 836, + }, + "source": "Hey ho ", + "start": Position { + "column": 14, + "line": 42, + "offset": 829, + }, + }, + "raw": "Hey ho ", + "unicode": false, + "value": "Hey ho ", + }, + "kind": "encapsedpart", + "loc": Location { + "end": Position { + "column": 21, + "line": 42, + "offset": 836, + }, + "source": "Hey ho ", + "start": Position { + "column": 14, + "line": 42, + "offset": 829, + }, + }, + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 26, + "line": 42, + "offset": 841, + }, + "source": "$name", + "start": Position { + "column": 21, + "line": 42, + "offset": 836, + }, + }, + "name": "name", + }, + "kind": "encapsedpart", + "loc": Location { + "end": Position { + "column": 26, + "line": 42, + "offset": 841, + }, + "source": "$name", + "start": Position { + "column": 21, + "line": 42, + "offset": 836, + }, + }, + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 28, + "line": 42, + "offset": 843, + }, + "source": ", ", + "start": Position { + "column": 26, + "line": 42, + "offset": 841, + }, + }, + "raw": ", ", + "unicode": false, + "value": ", ", + }, + "kind": "encapsedpart", + "loc": Location { + "end": Position { + "column": 28, + "line": 42, + "offset": 843, + }, + "source": ", ", + "start": Position { + "column": 26, + "line": 42, + "offset": 841, + }, + }, + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 37, + "line": 42, + "offset": 852, + }, + "source": "$greeting", + "start": Position { + "column": 28, + "line": 42, + "offset": 843, + }, + }, + "name": "greeting", + }, + "kind": "encapsedpart", + "loc": Location { + "end": Position { + "column": 37, + "line": 42, + "offset": 852, + }, + "source": "$greeting", + "start": Position { + "column": 28, + "line": 42, + "offset": 843, + }, + }, + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 39, + "line": 42, + "offset": 854, + }, + "source": " !", + "start": Position { + "column": 37, + "line": 42, + "offset": 852, + }, + }, + "raw": " !", + "unicode": false, + "value": " !", + }, + "kind": "encapsedpart", + "loc": Location { + "end": Position { + "column": 39, + "line": 42, + "offset": 854, + }, + "source": " !", + "start": Position { + "column": 37, + "line": 42, + "offset": 852, + }, + }, + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 41, + "line": 42, + "offset": 856, + }, + "source": "echo "Hey ho $name, $greeting !";", + "start": Position { + "column": 8, + "line": 42, + "offset": 823, + }, + }, + "shortForm": false, + }, + Continue { + "kind": "continue", + "level": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 21, + "line": 43, + "offset": 878, + }, + "source": "$foo", + "start": Position { + "column": 17, + "line": 43, + "offset": 874, + }, + }, + "name": "foo", + }, + "loc": Location { + "end": Position { + "column": 22, + "line": 43, + "offset": 879, + }, + "source": "continue $foo;", + "start": Position { + "column": 8, + "line": 43, + "offset": 865, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 7, + "line": 44, + "offset": 887, + }, + "source": "{ + echo "Hey ho $name, $greeting !"; + continue $foo; + }", + "start": Position { + "column": 50, + "line": 41, + "offset": 813, + }, + }, + }, + "key": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 35, + "line": 41, + "offset": 798, + }, + "source": "$name", + "start": Position { + "column": 30, + "line": 41, + "offset": 793, + }, + }, + "name": "name", + }, + "kind": "foreach", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 41, + "offset": 763, + }, + "source": "// do not wanna do +", + "start": Position { + "column": 6, + "line": 40, + "offset": 744, + }, + }, + "offset": 744, + "value": "// do not wanna do +", + }, + ], + "loc": Location { + "end": Position { + "column": 7, + "line": 44, + "offset": 887, + }, + "source": "foreach($this->dwarf as $name => $greeting) { + echo "Hey ho $name, $greeting !"; + continue $foo; + }", + "start": Position { + "column": 6, + "line": 41, + "offset": 769, + }, + }, + "shortForm": false, + "source": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 26, + "line": 41, + "offset": 789, + }, + "source": "$this->dwarf", + "start": Position { + "column": 14, + "line": 41, + "offset": 777, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 26, + "line": 41, + "offset": 789, + }, + "source": "dwarf", + "start": Position { + "column": 21, + "line": 41, + "offset": 784, + }, + }, + "name": "dwarf", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 41, + "offset": 782, + }, + "source": "$this", + "start": Position { + "column": 14, + "line": 41, + "offset": 777, + }, + }, + "name": "this", + }, + }, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 48, + "line": 41, + "offset": 811, + }, + "source": "$greeting", + "start": Position { + "column": 39, + "line": 41, + "offset": 802, + }, + }, + "name": "greeting", + }, + }, + Throw { + "kind": "throw", + "loc": Location { + "end": Position { + "column": 40, + "line": 45, + "offset": 928, + }, + "source": "throw new \\ComeToHome('Thats it');", + "start": Position { + "column": 6, + "line": 45, + "offset": 894, + }, + }, + "what": New { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 38, + "line": 45, + "offset": 926, + }, + "source": "'Thats it'", + "start": Position { + "column": 28, + "line": 45, + "offset": 916, + }, + }, + "raw": "'Thats it'", + "unicode": false, + "value": "Thats it", + }, + ], + "kind": "new", + "loc": Location { + "end": Position { + "column": 39, + "line": 45, + "offset": 927, + }, + "source": "new \\ComeToHome('Thats it')", + "start": Position { + "column": 12, + "line": 45, + "offset": 900, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 27, + "line": 45, + "offset": 915, + }, + "source": "\\ComeToHome", + "start": Position { + "column": 16, + "line": 45, + "offset": 904, + }, + }, + "name": "\\ComeToHome", + "resolution": "fqn", + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 5, + "line": 46, + "offset": 934, + }, + "source": "{ + // do not wanna do + foreach($this->dwarf as $name => $greeting) { + echo "Hey ho $name, $greeting !"; + continue $foo; + } + throw new \\ComeToHome('Thats it'); + }", + "start": Position { + "column": 40, + "line": 39, + "offset": 736, + }, + }, + }, + "byref": false, + "isAbstract": false, + "isFinal": true, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "loc": Location { + "end": Position { + "column": 7, + "line": 38, + "offset": 695, + }, + "source": "/** + * Something is done here + */", + "start": Position { + "column": 4, + "line": 36, + "offset": 654, + }, + }, + "offset": 654, + "value": "/** + * Something is done here + */", + }, + ], + "loc": Location { + "end": Position { + "column": 5, + "line": 46, + "offset": 934, + }, + "source": "final public function doSomething()", + "start": Position { + "column": 4, + "line": 39, + "offset": 700, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 37, + "line": 39, + "offset": 733, + }, + "source": "doSomething", + "start": Position { + "column": 26, + "line": 39, + "offset": 722, + }, + }, + "name": "doSomething", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": [ + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 51, + "line": 25, + "offset": 439, + }, + "source": "namespace\\fooBaz", + "start": Position { + "column": 35, + "line": 25, + "offset": 423, + }, + }, + "name": "fooBaz", + "resolution": "rn", + }, + ], + "isAbstract": true, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "loc": Location { + "end": Position { + "column": 5, + "line": 24, + "offset": 387, + }, + "source": "/** + * a class + */", + "start": Position { + "column": 2, + "line": 22, + "offset": 365, + }, + }, + "offset": 365, + "value": "/** + * a class + */", + }, + ], + "loc": Location { + "end": Position { + "column": 3, + "line": 47, + "offset": 938, + }, + "source": "abstract class fooBar implements namespace\\fooBaz { + use Line; + use foo, bar { + foo::baz insteadof bar; + bar::foo as baz; + } + const FOOBAR = 'BARFOO'; + protected $dwarf = [ + 'sneezy' => 'achoum', + 'bashful' => 'tadah' + ]; + /** + * Something is done here + */ + final public function doSomething() { + // do not wanna do + foreach($this->dwarf as $name => $greeting) { + echo "Hey ho $name, $greeting !"; + continue $foo; + } + throw new \\ComeToHome('Thats it'); + } + }", + "start": Position { + "column": 2, + "line": 25, + "offset": 390, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 23, + "line": 25, + "offset": 411, + }, + "source": "fooBar", + "start": Position { + "column": 17, + "line": 25, + "offset": 405, + }, + }, + "name": "fooBar", + }, + }, + Interface { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": null, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 39, + "line": 50, + "offset": 1014, + }, + "source": "public function Am_I_Uggly() : bool", + "start": Position { + "column": 4, + "line": 50, + "offset": 979, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 30, + "line": 50, + "offset": 1005, + }, + "source": "Am_I_Uggly", + "start": Position { + "column": 20, + "line": 50, + "offset": 995, + }, + }, + "name": "Am_I_Uggly", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 39, + "line": 50, + "offset": 1014, + }, + "source": "bool", + "start": Position { + "column": 35, + "line": 50, + "offset": 1010, + }, + }, + "name": "bool", + "raw": "bool", + }, + "visibility": "public", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": null, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 38, + "line": 51, + "offset": 1054, + }, + "source": "protected function broken() : bool", + "start": Position { + "column": 4, + "line": 51, + "offset": 1020, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 29, + "line": 51, + "offset": 1045, + }, + "source": "broken", + "start": Position { + "column": 23, + "line": 51, + "offset": 1039, + }, + }, + "name": "broken", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 38, + "line": 51, + "offset": 1054, + }, + "source": "bool", + "start": Position { + "column": 34, + "line": 51, + "offset": 1050, + }, + }, + "name": "bool", + "raw": "bool", + }, + "visibility": "protected", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": null, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": true, + "kind": "method", + "loc": Location { + "end": Position { + "column": 55, + "line": 52, + "offset": 1111, + }, + "source": "static protected function isWhiteSnowAlive() : bool", + "start": Position { + "column": 4, + "line": 52, + "offset": 1060, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 46, + "line": 52, + "offset": 1102, + }, + "source": "isWhiteSnowAlive", + "start": Position { + "column": 30, + "line": 52, + "offset": 1086, + }, + }, + "name": "isWhiteSnowAlive", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 55, + "line": 52, + "offset": 1111, + }, + "source": "bool", + "start": Position { + "column": 51, + "line": 52, + "offset": 1107, + }, + }, + "name": "bool", + "raw": "bool", + }, + "visibility": "protected", + }, + ], + "extends": [ + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 32, + "line": 49, + "offset": 972, + }, + "source": "Object", + "start": Position { + "column": 26, + "line": 49, + "offset": 966, + }, + }, + "name": "Object", + "resolution": "uqn", + }, + ], + "kind": "interface", + "loc": Location { + "end": Position { + "column": 3, + "line": 53, + "offset": 1116, + }, + "source": "interface Miror extends Object { + public function Am_I_Uggly() : bool; + protected function broken() : bool; + static protected function isWhiteSnowAlive() : bool; + }", + "start": Position { + "column": 2, + "line": 49, + "offset": 942, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 17, + "line": 49, + "offset": 957, + }, + "source": "Miror", + "start": Position { + "column": 12, + "line": 49, + "offset": 952, + }, + }, + "name": "Miror", + }, + }, + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Yield { + "key": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 16, + "line": 56, + "offset": 1154, + }, + "source": "'ator'", + "start": Position { + "column": 10, + "line": 56, + "offset": 1148, + }, + }, + "raw": "'ator'", + "unicode": false, + "value": "ator", + }, + "kind": "yield", + "loc": Location { + "end": Position { + "column": 25, + "line": 56, + "offset": 1163, + }, + "source": "yield 'ator' => $foo;", + "start": Position { + "column": 4, + "line": 56, + "offset": 1142, + }, + }, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 24, + "line": 56, + "offset": 1162, + }, + "source": "$foo", + "start": Position { + "column": 20, + "line": 56, + "offset": 1158, + }, + }, + "name": "foo", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 25, + "line": 56, + "offset": 1163, + }, + "source": "yield 'ator' => $foo;", + "start": Position { + "column": 4, + "line": 56, + "offset": 1142, + }, + }, + }, + ExpressionStatement { + "expression": YieldFrom { + "kind": "yieldfrom", + "loc": Location { + "end": Position { + "column": 24, + "line": 57, + "offset": 1188, + }, + "source": "yield from iter(50);", + "start": Position { + "column": 4, + "line": 57, + "offset": 1168, + }, + }, + "value": Call { + "arguments": [ + Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 22, + "line": 57, + "offset": 1186, + }, + "source": "50", + "start": Position { + "column": 20, + "line": 57, + "offset": 1184, + }, + }, + "value": "50", + }, + ], + "kind": "call", + "loc": Location { + "end": Position { + "column": 23, + "line": 57, + "offset": 1187, + }, + "source": "iter(50)", + "start": Position { + "column": 15, + "line": 57, + "offset": 1179, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 19, + "line": 57, + "offset": 1183, + }, + "source": "iter", + "start": Position { + "column": 15, + "line": 57, + "offset": 1179, + }, + }, + "name": "iter", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 24, + "line": 57, + "offset": 1188, + }, + "source": "yield from iter(50);", + "start": Position { + "column": 4, + "line": 57, + "offset": 1168, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 3, + "line": 58, + "offset": 1192, + }, + "source": "{ + yield 'ator' => $foo; + yield from iter(50); + }", + "start": Position { + "column": 18, + "line": 55, + "offset": 1136, + }, + }, + }, + "byref": false, + "kind": "function", + "loc": Location { + "end": Position { + "column": 3, + "line": 58, + "offset": 1192, + }, + "source": "function iter()", + "start": Position { + "column": 2, + "line": 55, + "offset": 1120, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 15, + "line": 55, + "offset": 1133, + }, + "source": "iter", + "start": Position { + "column": 11, + "line": 55, + "offset": 1129, + }, + }, + "name": "iter", + }, + "nullable": false, + "type": null, + }, + Trait { + "body": [ + Method { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "loc": Location { + "end": Position { + "column": 44, + "line": 61, + "offset": 1253, + }, + "source": "bool $arrow = false", + "start": Position { + "column": 25, + "line": 61, + "offset": 1234, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 36, + "line": 61, + "offset": 1245, + }, + "source": "$arrow", + "start": Position { + "column": 30, + "line": 61, + "offset": 1239, + }, + }, + "name": "arrow", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 29, + "line": 61, + "offset": 1238, + }, + "source": "bool", + "start": Position { + "column": 25, + "line": 61, + "offset": 1234, + }, + }, + "name": "bool", + "raw": "bool", + }, + "value": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 44, + "line": 61, + "offset": 1253, + }, + "source": "false", + "start": Position { + "column": 39, + "line": 61, + "offset": 1248, + }, + }, + "raw": "false", + "value": false, + }, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Switch { + "body": Block { + "children": [ + Case { + "body": Block { + "children": [], + "kind": "block", + "loc": Location { + "end": Position { + "column": 19, + "line": 63, + "offset": 1314, + }, + "source": " + ", + "start": Position { + "column": 8, + "line": 64, + "offset": 1323, + }, + }, + }, + "kind": "case", + "loc": Location { + "end": Position { + "column": 19, + "line": 63, + "offset": 1314, + }, + "source": "case 'dot':", + "start": Position { + "column": 8, + "line": 63, + "offset": 1303, + }, + }, + "test": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 18, + "line": 63, + "offset": 1313, + }, + "source": "'dot'", + "start": Position { + "column": 13, + "line": 63, + "offset": 1308, + }, + }, + "raw": "'dot'", + "unicode": false, + "value": "dot", + }, + }, + Case { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 15, + "line": 65, + "offset": 1352, + }, + "source": "$body", + "start": Position { + "column": 10, + "line": 65, + "offset": 1347, + }, + }, + "name": "body", + }, + "loc": Location { + "end": Position { + "column": 27, + "line": 65, + "offset": 1364, + }, + "source": "$body = '......';", + "start": Position { + "column": 10, + "line": 65, + "offset": 1347, + }, + }, + "operator": "=", + "right": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 26, + "line": 65, + "offset": 1363, + }, + "source": "'......'", + "start": Position { + "column": 18, + "line": 65, + "offset": 1355, + }, + }, + "raw": "'......'", + "unicode": false, + "value": "......", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 27, + "line": 65, + "offset": 1364, + }, + "source": "$body = '......';", + "start": Position { + "column": 10, + "line": 65, + "offset": 1347, + }, + }, + }, + Break { + "kind": "break", + "level": null, + "loc": Location { + "end": Position { + "column": 16, + "line": 66, + "offset": 1381, + }, + "source": "break;", + "start": Position { + "column": 10, + "line": 66, + "offset": 1375, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 16, + "line": 66, + "offset": 1381, + }, + "source": "$body = '......'; + break;", + "start": Position { + "column": 10, + "line": 65, + "offset": 1347, + }, + }, + }, + "kind": "case", + "loc": Location { + "end": Position { + "column": 16, + "line": 66, + "offset": 1381, + }, + "source": "case 'point': + $body = '......'; + break;", + "start": Position { + "column": 8, + "line": 64, + "offset": 1323, + }, + }, + "test": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 20, + "line": 64, + "offset": 1335, + }, + "source": "'point'", + "start": Position { + "column": 13, + "line": 64, + "offset": 1328, + }, + }, + "raw": "'point'", + "unicode": false, + "value": "point", + }, + }, + Case { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 15, + "line": 68, + "offset": 1414, + }, + "source": "$body", + "start": Position { + "column": 10, + "line": 68, + "offset": 1409, + }, + }, + "name": "body", + }, + "loc": Location { + "end": Position { + "column": 26, + "line": 68, + "offset": 1425, + }, + "source": "$body = '-----';", + "start": Position { + "column": 10, + "line": 68, + "offset": 1409, + }, + }, + "operator": "=", + "right": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 25, + "line": 68, + "offset": 1424, + }, + "source": "'-----'", + "start": Position { + "column": 18, + "line": 68, + "offset": 1417, + }, + }, + "raw": "'-----'", + "unicode": false, + "value": "-----", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 26, + "line": 68, + "offset": 1425, + }, + "source": "$body = '-----';", + "start": Position { + "column": 10, + "line": 68, + "offset": 1409, + }, + }, + }, + Break { + "kind": "break", + "level": null, + "loc": Location { + "end": Position { + "column": 16, + "line": 69, + "offset": 1442, + }, + "source": "break;", + "start": Position { + "column": 10, + "line": 69, + "offset": 1436, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 16, + "line": 69, + "offset": 1442, + }, + "source": "$body = '-----'; + break;", + "start": Position { + "column": 10, + "line": 68, + "offset": 1409, + }, + }, + }, + "kind": "case", + "loc": Location { + "end": Position { + "column": 16, + "line": 69, + "offset": 1442, + }, + "source": "default: + $body = '-----'; + break;", + "start": Position { + "column": 8, + "line": 67, + "offset": 1390, + }, + }, + "test": null, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 7, + "line": 70, + "offset": 1450, + }, + "source": "{ + case 'dot': + case 'point': + $body = '......'; + break; + default: + $body = '-----'; + break; + }", + "start": Position { + "column": 27, + "line": 62, + "offset": 1293, + }, + }, + }, + "kind": "switch", + "loc": Location { + "end": Position { + "column": 7, + "line": 70, + "offset": 1450, + }, + "source": "switch($this->style) { + case 'dot': + case 'point': + $body = '......'; + break; + default: + $body = '-----'; + break; + }", + "start": Position { + "column": 6, + "line": 62, + "offset": 1272, + }, + }, + "shortForm": false, + "test": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 25, + "line": 62, + "offset": 1291, + }, + "source": "$this->style", + "start": Position { + "column": 13, + "line": 62, + "offset": 1279, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 25, + "line": 62, + "offset": 1291, + }, + "source": "style", + "start": Position { + "column": 20, + "line": 62, + "offset": 1286, + }, + }, + "name": "style", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 18, + "line": 62, + "offset": 1284, + }, + "source": "$this", + "start": Position { + "column": 13, + "line": 62, + "offset": 1279, + }, + }, + "name": "this", + }, + }, + }, + Return { + "expr": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 18, + "line": 71, + "offset": 1469, + }, + "source": "$body", + "start": Position { + "column": 13, + "line": 71, + "offset": 1464, + }, + }, + "name": "body", + }, + "loc": Location { + "end": Position { + "column": 40, + "line": 71, + "offset": 1491, + }, + "source": "$body . ($arrow ? '>' : '')", + "start": Position { + "column": 13, + "line": 71, + "offset": 1464, + }, + }, + "right": RetIf { + "falseExpr": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 39, + "line": 71, + "offset": 1490, + }, + "source": "''", + "start": Position { + "column": 37, + "line": 71, + "offset": 1488, + }, + }, + "raw": "''", + "unicode": false, + "value": "", + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 39, + "line": 71, + "offset": 1490, + }, + "source": "$arrow ? '>' : ''", + "start": Position { + "column": 22, + "line": 71, + "offset": 1473, + }, + }, + "parenthesizedExpression": true, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 28, + "line": 71, + "offset": 1479, + }, + "source": "$arrow", + "start": Position { + "column": 22, + "line": 71, + "offset": 1473, + }, + }, + "name": "arrow", + }, + "trueExpr": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 34, + "line": 71, + "offset": 1485, + }, + "source": "'>'", + "start": Position { + "column": 31, + "line": 71, + "offset": 1482, + }, + }, + "raw": "'>'", + "unicode": false, + "value": ">", + }, + }, + "type": ".", + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 41, + "line": 71, + "offset": 1492, + }, + "source": "return $body . ($arrow ? '>' : '');", + "start": Position { + "column": 6, + "line": 71, + "offset": 1457, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 5, + "line": 72, + "offset": 1498, + }, + "source": "{ + switch($this->style) { + case 'dot': + case 'point': + $body = '......'; + break; + default: + $body = '-----'; + break; + } + return $body . ($arrow ? '>' : ''); + }", + "start": Position { + "column": 55, + "line": 61, + "offset": 1264, + }, + }, + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 5, + "line": 72, + "offset": 1498, + }, + "source": "public function draw(bool $arrow = false) : string", + "start": Position { + "column": 4, + "line": 61, + "offset": 1213, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 24, + "line": 61, + "offset": 1233, + }, + "source": "draw", + "start": Position { + "column": 20, + "line": 61, + "offset": 1229, + }, + }, + "name": "draw", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 54, + "line": 61, + "offset": 1263, + }, + "source": "string", + "start": Position { + "column": 48, + "line": 61, + "offset": 1257, + }, + }, + "name": "string", + "raw": "string", + }, + "visibility": "public", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Magic { + "kind": "magic", + "loc": Location { + "end": Position { + "column": 26, + "line": 74, + "offset": 1556, + }, + "source": "__NAMESPACE__", + "start": Position { + "column": 13, + "line": 74, + "offset": 1543, + }, + }, + "raw": "__NAMESPACE__", + "value": "__NAMESPACE__", + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 27, + "line": 74, + "offset": 1557, + }, + "source": "return __NAMESPACE__;", + "start": Position { + "column": 6, + "line": 74, + "offset": 1536, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 5, + "line": 75, + "offset": 1563, + }, + "source": "{ + return __NAMESPACE__; + }", + "start": Position { + "column": 29, + "line": 73, + "offset": 1528, + }, + }, + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 5, + "line": 75, + "offset": 1563, + }, + "source": "private function shuut()", + "start": Position { + "column": 4, + "line": 73, + "offset": 1503, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 26, + "line": 73, + "offset": 1525, + }, + "source": "shuut", + "start": Position { + "column": 21, + "line": 73, + "offset": 1520, + }, + }, + "name": "shuut", + }, + "nullable": false, + "type": null, + "visibility": "private", + }, + ], + "kind": "trait", + "loc": Location { + "end": Position { + "column": 3, + "line": 76, + "offset": 1567, + }, + "source": "trait Line { + public function draw(bool $arrow = false) : string { + switch($this->style) { + case 'dot': + case 'point': + $body = '......'; + break; + default: + $body = '-----'; + break; + } + return $body . ($arrow ? '>' : ''); + } + private function shuut() { + return __NAMESPACE__; + } + }", + "start": Position { + "column": 2, + "line": 60, + "offset": 1196, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 12, + "line": 60, + "offset": 1206, + }, + "source": "Line", + "start": Position { + "column": 8, + "line": 60, + "offset": 1202, + }, + }, + "name": "Line", + }, + }, + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Global { + "items": [ + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 20, + "line": 80, + "offset": 1640, + }, + "source": "$persians", + "start": Position { + "column": 11, + "line": 80, + "offset": 1631, + }, + }, + "name": "persians", + }, + ], + "kind": "global", + "loc": Location { + "end": Position { + "column": 21, + "line": 80, + "offset": 1641, + }, + "source": "global $persians;", + "start": Position { + "column": 4, + "line": 80, + "offset": 1624, + }, + }, + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 82, + "offset": 1653, + }, + "source": "$index", + "start": Position { + "column": 4, + "line": 82, + "offset": 1647, + }, + }, + "name": "index", + }, + "loc": Location { + "end": Position { + "column": 16, + "line": 82, + "offset": 1659, + }, + "source": "$index = -1;", + "start": Position { + "column": 4, + "line": 82, + "offset": 1647, + }, + }, + "operator": "=", + "right": Unary { + "kind": "unary", + "loc": Location { + "end": Position { + "column": 15, + "line": 82, + "offset": 1658, + }, + "source": "-1", + "start": Position { + "column": 13, + "line": 82, + "offset": 1656, + }, + }, + "type": "-", + "what": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 15, + "line": 82, + "offset": 1658, + }, + "source": "1", + "start": Position { + "column": 14, + "line": 82, + "offset": 1657, + }, + }, + "value": "1", + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 16, + "line": 82, + "offset": 1659, + }, + "source": "$index = -1;", + "start": Position { + "column": 4, + "line": 82, + "offset": 1647, + }, + }, + }, + Label { + "kind": "label", + "loc": Location { + "end": Position { + "column": 5, + "line": 83, + "offset": 1665, + }, + "source": "next:", + "start": Position { + "column": 0, + "line": 83, + "offset": 1660, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 4, + "line": 83, + "offset": 1664, + }, + "source": "next", + "start": Position { + "column": 0, + "line": 83, + "offset": 1660, + }, + }, + "name": "next", + }, + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 8, + "line": 84, + "offset": 1674, + }, + "source": "$guy", + "start": Position { + "column": 4, + "line": 84, + "offset": 1670, + }, + }, + "name": "guy", + }, + "loc": Location { + "end": Position { + "column": 31, + "line": 84, + "offset": 1697, + }, + "source": "$guy = $persians[++$index];", + "start": Position { + "column": 4, + "line": 84, + "offset": 1670, + }, + }, + "operator": "=", + "right": OffsetLookup { + "kind": "offsetlookup", + "loc": Location { + "end": Position { + "column": 30, + "line": 84, + "offset": 1696, + }, + "source": "$persians[++$index]", + "start": Position { + "column": 11, + "line": 84, + "offset": 1677, + }, + }, + "offset": Pre { + "kind": "pre", + "loc": Location { + "end": Position { + "column": 29, + "line": 84, + "offset": 1695, + }, + "source": "++$index", + "start": Position { + "column": 21, + "line": 84, + "offset": 1687, + }, + }, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 29, + "line": 84, + "offset": 1695, + }, + "source": "$index", + "start": Position { + "column": 23, + "line": 84, + "offset": 1689, + }, + }, + "name": "index", + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 20, + "line": 84, + "offset": 1686, + }, + "source": "$persians", + "start": Position { + "column": 11, + "line": 84, + "offset": 1677, + }, + }, + "name": "persians", + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 31, + "line": 84, + "offset": 1697, + }, + "source": "$guy = $persians[++$index];", + "start": Position { + "column": 4, + "line": 84, + "offset": 1670, + }, + }, + }, + If { + "alternate": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + variadic { + "kind": "variadic", + "loc": Location { + "end": Position { + "column": 24, + "line": 88, + "offset": 1789, + }, + "source": "...$foo", + "start": Position { + "column": 17, + "line": 88, + "offset": 1782, + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 24, + "line": 88, + "offset": 1789, + }, + "source": "$foo", + "start": Position { + "column": 20, + "line": 88, + "offset": 1785, + }, + }, + "name": "foo", + }, + }, + ], + "kind": "call", + "loc": Location { + "end": Position { + "column": 26, + "line": 88, + "offset": 1791, + }, + "source": "$guy->kick(...$foo);", + "start": Position { + "column": 6, + "line": 88, + "offset": 1771, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 16, + "line": 88, + "offset": 1781, + }, + "source": "$guy->kick", + "start": Position { + "column": 6, + "line": 88, + "offset": 1771, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 16, + "line": 88, + "offset": 1781, + }, + "source": "kick", + "start": Position { + "column": 12, + "line": 88, + "offset": 1777, + }, + }, + "name": "kick", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 88, + "offset": 1775, + }, + "source": "$guy", + "start": Position { + "column": 6, + "line": 88, + "offset": 1771, + }, + }, + "name": "guy", + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 26, + "line": 88, + "offset": 1791, + }, + "source": "$guy->kick(...$foo);", + "start": Position { + "column": 6, + "line": 88, + "offset": 1771, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 5, + "line": 89, + "offset": 1797, + }, + "source": "{ + $guy->kick(...$foo); + }", + "start": Position { + "column": 11, + "line": 87, + "offset": 1763, + }, + }, + }, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Silent { + "expr": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 19, + "line": 86, + "offset": 1750, + }, + "source": "$guy->kill()", + "start": Position { + "column": 7, + "line": 86, + "offset": 1738, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 17, + "line": 86, + "offset": 1748, + }, + "source": "$guy->kill", + "start": Position { + "column": 7, + "line": 86, + "offset": 1738, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 17, + "line": 86, + "offset": 1748, + }, + "source": "kill", + "start": Position { + "column": 13, + "line": 86, + "offset": 1744, + }, + }, + "name": "kill", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 11, + "line": 86, + "offset": 1742, + }, + "source": "$guy", + "start": Position { + "column": 7, + "line": 86, + "offset": 1738, + }, + }, + "name": "guy", + }, + }, + }, + "kind": "silent", + "loc": Location { + "end": Position { + "column": 20, + "line": 86, + "offset": 1751, + }, + "source": "@$guy->kill();", + "start": Position { + "column": 6, + "line": 86, + "offset": 1737, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 20, + "line": 86, + "offset": 1751, + }, + "source": "@$guy->kill();", + "start": Position { + "column": 6, + "line": 86, + "offset": 1737, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 5, + "line": 87, + "offset": 1757, + }, + "source": "{ + @$guy->kill(); + }", + "start": Position { + "column": 31, + "line": 85, + "offset": 1729, + }, + }, + }, + "kind": "if", + "loc": Location { + "end": Position { + "column": 5, + "line": 89, + "offset": 1797, + }, + "source": "if(rand(0, 10)>5 || false) { + @$guy->kill(); + } else { + $guy->kick(...$foo); + }", + "start": Position { + "column": 4, + "line": 85, + "offset": 1702, + }, + }, + "shortForm": false, + "test": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Call { + "arguments": [ + Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 13, + "line": 85, + "offset": 1711, + }, + "source": "0", + "start": Position { + "column": 12, + "line": 85, + "offset": 1710, + }, + }, + "value": "0", + }, + Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 17, + "line": 85, + "offset": 1715, + }, + "source": "10", + "start": Position { + "column": 15, + "line": 85, + "offset": 1713, + }, + }, + "value": "10", + }, + ], + "kind": "call", + "loc": Location { + "end": Position { + "column": 18, + "line": 85, + "offset": 1716, + }, + "source": "rand(0, 10)", + "start": Position { + "column": 7, + "line": 85, + "offset": 1705, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 11, + "line": 85, + "offset": 1709, + }, + "source": "rand", + "start": Position { + "column": 7, + "line": 85, + "offset": 1705, + }, + }, + "name": "rand", + "resolution": "uqn", + }, + }, + "loc": Location { + "end": Position { + "column": 20, + "line": 85, + "offset": 1718, + }, + "source": "rand(0, 10)>5", + "start": Position { + "column": 7, + "line": 85, + "offset": 1705, + }, + }, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 20, + "line": 85, + "offset": 1718, + }, + "source": "5", + "start": Position { + "column": 19, + "line": 85, + "offset": 1717, + }, + }, + "value": "5", + }, + "type": ">", + }, + "loc": Location { + "end": Position { + "column": 29, + "line": 85, + "offset": 1727, + }, + "source": "rand(0, 10)>5 || false", + "start": Position { + "column": 7, + "line": 85, + "offset": 1705, + }, + }, + "right": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 29, + "line": 85, + "offset": 1727, + }, + "source": "false", + "start": Position { + "column": 24, + "line": 85, + "offset": 1722, + }, + }, + "raw": "false", + "value": false, + }, + "type": "||", + }, + }, + If { + "alternate": null, + "body": Goto { + "kind": "goto", + "label": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 49, + "line": 90, + "offset": 1847, + }, + "source": "next", + "start": Position { + "column": 45, + "line": 90, + "offset": 1843, + }, + }, + "name": "next", + }, + "loc": Location { + "end": Position { + "column": 50, + "line": 90, + "offset": 1848, + }, + "source": "goto next;", + "start": Position { + "column": 40, + "line": 90, + "offset": 1838, + }, + }, + }, + "kind": "if", + "loc": Location { + "end": Position { + "column": 50, + "line": 90, + "offset": 1848, + }, + "source": "if ((int)$index < count($persians)) goto next;", + "start": Position { + "column": 4, + "line": 90, + "offset": 1802, + }, + }, + "shortForm": false, + "test": Bin { + "kind": "bin", + "left": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 90, + "offset": 1817, + }, + "source": "$index", + "start": Position { + "column": 13, + "line": 90, + "offset": 1811, + }, + }, + "name": "index", + }, + "kind": "cast", + "loc": Location { + "end": Position { + "column": 19, + "line": 90, + "offset": 1817, + }, + "source": "(int)$index", + "start": Position { + "column": 8, + "line": 90, + "offset": 1806, + }, + }, + "raw": "(int)", + "type": "int", + }, + "loc": Location { + "end": Position { + "column": 38, + "line": 90, + "offset": 1836, + }, + "source": "(int)$index < count($persians)", + "start": Position { + "column": 8, + "line": 90, + "offset": 1806, + }, + }, + "right": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 37, + "line": 90, + "offset": 1835, + }, + "source": "$persians", + "start": Position { + "column": 28, + "line": 90, + "offset": 1826, + }, + }, + "name": "persians", + }, + ], + "kind": "call", + "loc": Location { + "end": Position { + "column": 38, + "line": 90, + "offset": 1836, + }, + "source": "count($persians)", + "start": Position { + "column": 22, + "line": 90, + "offset": 1820, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 27, + "line": 90, + "offset": 1825, + }, + "source": "count", + "start": Position { + "column": 22, + "line": 90, + "offset": 1820, + }, + }, + "name": "count", + "resolution": "uqn", + }, + }, + "type": "<", + }, + }, + Return { + "expr": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 14, + "line": 92, + "offset": 1864, + }, + "source": "300", + "start": Position { + "column": 11, + "line": 92, + "offset": 1861, + }, + }, + "value": "300", + }, + "loc": Location { + "end": Position { + "column": 18, + "line": 92, + "offset": 1868, + }, + "source": "300 | 5", + "start": Position { + "column": 11, + "line": 92, + "offset": 1861, + }, + }, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 18, + "line": 92, + "offset": 1868, + }, + "source": "5", + "start": Position { + "column": 17, + "line": 92, + "offset": 1867, + }, + }, + "value": "5", + }, + "type": "|", + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 19, + "line": 92, + "offset": 1869, + }, + "source": "return 300 | 5;", + "start": Position { + "column": 4, + "line": 92, + "offset": 1854, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 3, + "line": 93, + "offset": 1873, + }, + "source": "{ + global $persians; + + $index = -1; +next: + $guy = $persians[++$index]; + if(rand(0, 10)>5 || false) { + @$guy->kill(); + } else { + $guy->kick(...$foo); + } + if ((int)$index < count($persians)) goto next; + + return 300 | 5; + }", + "start": Position { + "column": 27, + "line": 79, + "offset": 1618, + }, + }, + }, + "byref": false, + "kind": "function", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 79, + "offset": 1591, + }, + "source": "// this is SPARTA ! +", + "start": Position { + "column": 2, + "line": 78, + "offset": 1571, + }, + }, + "offset": 1571, + "value": "// this is SPARTA ! +", + }, + ], + "loc": Location { + "end": Position { + "column": 3, + "line": 93, + "offset": 1873, + }, + "source": "function sparta() : ?int", + "start": Position { + "column": 2, + "line": 79, + "offset": 1593, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 17, + "line": 79, + "offset": 1608, + }, + "source": "sparta", + "start": Position { + "column": 11, + "line": 79, + "offset": 1602, + }, + }, + "name": "sparta", + }, + "nullable": true, + "type": TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 26, + "line": 79, + "offset": 1617, + }, + "source": "int", + "start": Position { + "column": 23, + "line": 79, + "offset": 1614, + }, + }, + "name": "int", + "raw": "int", + }, + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 6, + "line": 95, + "offset": 1881, + }, + "source": "$foo", + "start": Position { + "column": 2, + "line": 95, + "offset": 1877, + }, + }, + "name": "foo", + }, + "loc": Location { + "end": Position { + "column": 4, + "line": 131, + "offset": 2878, + }, + "source": "$foo = function(?int $bar = 42) use($something) : bool { + static $banana; + if($bar > fooBar::NUMBAR) { + while($bar) { + if ((int)calculateMeaningOfLife() === 42) { + break foo; + } else continue; + } + do { + ?> + Caesar: here I was + crazy()->boom([1, 2, 3]); + } catch(Coco|Nut $ex) { + $ex->printStackTrace(); + } finally { + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + } + } else { + for($i = 0; $i < count($this->banana); $i++) { + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + } + // @todo $this->a_$foo + return $$foo ?? false; + } + return empty(namespace\\FOOBAR); + };", + "start": Position { + "column": 2, + "line": 95, + "offset": 1877, + }, + }, + "operator": "=", + "right": Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "loc": Location { + "end": Position { + "column": 32, + "line": 95, + "offset": 1907, + }, + "source": "?int $bar = 42", + "start": Position { + "column": 18, + "line": 95, + "offset": 1893, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 27, + "line": 95, + "offset": 1902, + }, + "source": "$bar", + "start": Position { + "column": 23, + "line": 95, + "offset": 1898, + }, + }, + "name": "bar", + }, + "nullable": true, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 22, + "line": 95, + "offset": 1897, + }, + "source": "int", + "start": Position { + "column": 19, + "line": 95, + "offset": 1894, + }, + }, + "name": "int", + "raw": "int", + }, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 32, + "line": 95, + "offset": 1907, + }, + "source": "42", + "start": Position { + "column": 30, + "line": 95, + "offset": 1905, + }, + }, + "value": "42", + }, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Static { + "kind": "static", + "loc": Location { + "end": Position { + "column": 19, + "line": 96, + "offset": 1953, + }, + "source": "static $banana;", + "start": Position { + "column": 4, + "line": 96, + "offset": 1938, + }, + }, + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 18, + "line": 96, + "offset": 1952, + }, + "source": "$banana", + "start": Position { + "column": 11, + "line": 96, + "offset": 1945, + }, + }, + "name": "banana", + }, + ], + }, + If { + "alternate": If { + "alternate": Block { + "children": [ + For { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 124, + "offset": 2691, + }, + "source": "$x", + "start": Position { + "column": 8, + "line": 124, + "offset": 2689, + }, + }, + "name": "x", + }, + "loc": Location { + "end": Position { + "column": 34, + "line": 124, + "offset": 2715, + }, + "source": "$x %= ($i * 2) / ($i - 1);", + "start": Position { + "column": 8, + "line": 124, + "offset": 2689, + }, + }, + "operator": "%=", + "right": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 17, + "line": 124, + "offset": 2698, + }, + "source": "$i", + "start": Position { + "column": 15, + "line": 124, + "offset": 2696, + }, + }, + "name": "i", + }, + "loc": Location { + "end": Position { + "column": 21, + "line": 124, + "offset": 2702, + }, + "source": "$i * 2", + "start": Position { + "column": 15, + "line": 124, + "offset": 2696, + }, + }, + "parenthesizedExpression": true, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 21, + "line": 124, + "offset": 2702, + }, + "source": "2", + "start": Position { + "column": 20, + "line": 124, + "offset": 2701, + }, + }, + "value": "2", + }, + "type": "*", + }, + "loc": Location { + "end": Position { + "column": 33, + "line": 124, + "offset": 2714, + }, + "source": "($i * 2) / ($i - 1)", + "start": Position { + "column": 14, + "line": 124, + "offset": 2695, + }, + }, + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 28, + "line": 124, + "offset": 2709, + }, + "source": "$i", + "start": Position { + "column": 26, + "line": 124, + "offset": 2707, + }, + }, + "name": "i", + }, + "loc": Location { + "end": Position { + "column": 32, + "line": 124, + "offset": 2713, + }, + "source": "$i - 1", + "start": Position { + "column": 26, + "line": 124, + "offset": 2707, + }, + }, + "parenthesizedExpression": true, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 32, + "line": 124, + "offset": 2713, + }, + "source": "1", + "start": Position { + "column": 31, + "line": 124, + "offset": 2712, + }, + }, + "value": "1", + }, + "type": "-", + }, + "type": "/", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 34, + "line": 124, + "offset": 2715, + }, + "source": "$x %= ($i * 2) / ($i - 1);", + "start": Position { + "column": 8, + "line": 124, + "offset": 2689, + }, + }, + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 13, + "line": 125, + "offset": 2729, + }, + "source": "$what", + "start": Position { + "column": 8, + "line": 125, + "offset": 2724, + }, + }, + "name": "what", + }, + "loc": Location { + "end": Position { + "column": 49, + "line": 125, + "offset": 2765, + }, + "source": "$what = $this->$x[++$i] ? 'yes!': 'noo!';", + "start": Position { + "column": 8, + "line": 125, + "offset": 2724, + }, + }, + "operator": "=", + "right": RetIf { + "falseExpr": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 48, + "line": 125, + "offset": 2764, + }, + "source": "'noo!'", + "start": Position { + "column": 42, + "line": 125, + "offset": 2758, + }, + }, + "raw": "'noo!'", + "unicode": false, + "value": "noo!", + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 48, + "line": 125, + "offset": 2764, + }, + "source": "$this->$x[++$i] ? 'yes!': 'noo!'", + "start": Position { + "column": 16, + "line": 125, + "offset": 2732, + }, + }, + "test": OffsetLookup { + "kind": "offsetlookup", + "loc": Location { + "end": Position { + "column": 31, + "line": 125, + "offset": 2747, + }, + "source": "$this->$x[++$i]", + "start": Position { + "column": 16, + "line": 125, + "offset": 2732, + }, + }, + "offset": Pre { + "kind": "pre", + "loc": Location { + "end": Position { + "column": 30, + "line": 125, + "offset": 2746, + }, + "source": "++$i", + "start": Position { + "column": 26, + "line": 125, + "offset": 2742, + }, + }, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 30, + "line": 125, + "offset": 2746, + }, + "source": "$i", + "start": Position { + "column": 28, + "line": 125, + "offset": 2744, + }, + }, + "name": "i", + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 25, + "line": 125, + "offset": 2741, + }, + "source": "$this->$x", + "start": Position { + "column": 16, + "line": 125, + "offset": 2732, + }, + }, + "offset": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 25, + "line": 125, + "offset": 2741, + }, + "source": "$x", + "start": Position { + "column": 23, + "line": 125, + "offset": 2739, + }, + }, + "name": "x", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 21, + "line": 125, + "offset": 2737, + }, + "source": "$this", + "start": Position { + "column": 16, + "line": 125, + "offset": 2732, + }, + }, + "name": "this", + }, + }, + }, + "trueExpr": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 40, + "line": 125, + "offset": 2756, + }, + "source": "'yes!'", + "start": Position { + "column": 34, + "line": 125, + "offset": 2750, + }, + }, + "raw": "'yes!'", + "unicode": false, + "value": "yes!", + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 49, + "line": 125, + "offset": 2765, + }, + "source": "$what = $this->$x[++$i] ? 'yes!': 'noo!';", + "start": Position { + "column": 8, + "line": 125, + "offset": 2724, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 7, + "line": 126, + "offset": 2773, + }, + "source": "{ + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + }", + "start": Position { + "column": 51, + "line": 123, + "offset": 2679, + }, + }, + }, + "increment": [ + Post { + "kind": "post", + "loc": Location { + "end": Position { + "column": 49, + "line": 123, + "offset": 2677, + }, + "source": "$i++", + "start": Position { + "column": 45, + "line": 123, + "offset": 2673, + }, + }, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 47, + "line": 123, + "offset": 2675, + }, + "source": "$i", + "start": Position { + "column": 45, + "line": 123, + "offset": 2673, + }, + }, + "name": "i", + }, + }, + ], + "init": [ + Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 123, + "offset": 2640, + }, + "source": "$i", + "start": Position { + "column": 10, + "line": 123, + "offset": 2638, + }, + }, + "name": "i", + }, + "loc": Location { + "end": Position { + "column": 16, + "line": 123, + "offset": 2644, + }, + "source": "$i = 0", + "start": Position { + "column": 10, + "line": 123, + "offset": 2638, + }, + }, + "operator": "=", + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 16, + "line": 123, + "offset": 2644, + }, + "source": "0", + "start": Position { + "column": 15, + "line": 123, + "offset": 2643, + }, + }, + "value": "0", + }, + }, + ], + "kind": "for", + "loc": Location { + "end": Position { + "column": 7, + "line": 126, + "offset": 2773, + }, + "source": "for($i = 0; $i < count($this->banana); $i++) { + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + }", + "start": Position { + "column": 6, + "line": 123, + "offset": 2634, + }, + }, + "shortForm": false, + "test": [ + Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 20, + "line": 123, + "offset": 2648, + }, + "source": "$i", + "start": Position { + "column": 18, + "line": 123, + "offset": 2646, + }, + }, + "name": "i", + }, + "loc": Location { + "end": Position { + "column": 43, + "line": 123, + "offset": 2671, + }, + "source": "$i < count($this->banana)", + "start": Position { + "column": 18, + "line": 123, + "offset": 2646, + }, + }, + "right": Call { + "arguments": [ + PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 42, + "line": 123, + "offset": 2670, + }, + "source": "$this->banana", + "start": Position { + "column": 29, + "line": 123, + "offset": 2657, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 42, + "line": 123, + "offset": 2670, + }, + "source": "banana", + "start": Position { + "column": 36, + "line": 123, + "offset": 2664, + }, + }, + "name": "banana", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 34, + "line": 123, + "offset": 2662, + }, + "source": "$this", + "start": Position { + "column": 29, + "line": 123, + "offset": 2657, + }, + }, + "name": "this", + }, + }, + ], + "kind": "call", + "loc": Location { + "end": Position { + "column": 43, + "line": 123, + "offset": 2671, + }, + "source": "count($this->banana)", + "start": Position { + "column": 23, + "line": 123, + "offset": 2651, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 28, + "line": 123, + "offset": 2656, + }, + "source": "count", + "start": Position { + "column": 23, + "line": 123, + "offset": 2651, + }, + }, + "name": "count", + "resolution": "uqn", + }, + }, + "type": "<", + }, + ], + }, + Return { + "expr": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 18, + "line": 128, + "offset": 2821, + }, + "source": "$$foo", + "start": Position { + "column": 13, + "line": 128, + "offset": 2816, + }, + }, + "name": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 18, + "line": 128, + "offset": 2821, + }, + "source": "$foo", + "start": Position { + "column": 14, + "line": 128, + "offset": 2817, + }, + }, + "name": "foo", + }, + }, + "loc": Location { + "end": Position { + "column": 27, + "line": 128, + "offset": 2830, + }, + "source": "$$foo ?? false", + "start": Position { + "column": 13, + "line": 128, + "offset": 2816, + }, + }, + "right": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 27, + "line": 128, + "offset": 2830, + }, + "source": "false", + "start": Position { + "column": 22, + "line": 128, + "offset": 2825, + }, + }, + "raw": "false", + "value": false, + }, + "type": "??", + }, + "kind": "return", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 128, + "offset": 2803, + }, + "source": "// @todo $this->a_$foo +", + "start": Position { + "column": 6, + "line": 127, + "offset": 2780, + }, + }, + "offset": 2780, + "value": "// @todo $this->a_$foo +", + }, + ], + "loc": Location { + "end": Position { + "column": 28, + "line": 128, + "offset": 2831, + }, + "source": "return $$foo ?? false;", + "start": Position { + "column": 6, + "line": 128, + "offset": 2809, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 5, + "line": 129, + "offset": 2837, + }, + "source": "{ + for($i = 0; $i < count($this->banana); $i++) { + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + } + // @todo $this->a_$foo + return $$foo ?? false; + }", + "start": Position { + "column": 11, + "line": 122, + "offset": 2626, + }, + }, + }, + "body": Block { + "children": [ + Try { + "always": Block { + "children": [ + If { + "alternate": null, + "body": Unset { + "kind": "unset", + "loc": Location { + "end": Position { + "column": 53, + "line": 115, + "offset": 2471, + }, + "source": "unset($bipbip, $ex);", + "start": Position { + "column": 33, + "line": 115, + "offset": 2451, + }, + }, + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 46, + "line": 115, + "offset": 2464, + }, + "source": "$bipbip", + "start": Position { + "column": 39, + "line": 115, + "offset": 2457, + }, + }, + "name": "bipbip", + }, + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 51, + "line": 115, + "offset": 2469, + }, + "source": "$ex", + "start": Position { + "column": 48, + "line": 115, + "offset": 2466, + }, + }, + "name": "ex", + }, + ], + }, + "kind": "if", + "loc": Location { + "end": Position { + "column": 53, + "line": 115, + "offset": 2471, + }, + "source": "if (isset($bipbip, $ex)) unset($bipbip, $ex);", + "start": Position { + "column": 8, + "line": 115, + "offset": 2426, + }, + }, + "shortForm": false, + "test": Isset { + "kind": "isset", + "loc": Location { + "end": Position { + "column": 31, + "line": 115, + "offset": 2449, + }, + "source": "isset($bipbip, $ex)", + "start": Position { + "column": 12, + "line": 115, + "offset": 2430, + }, + }, + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 25, + "line": 115, + "offset": 2443, + }, + "source": "$bipbip", + "start": Position { + "column": 18, + "line": 115, + "offset": 2436, + }, + }, + "name": "bipbip", + }, + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 30, + "line": 115, + "offset": 2448, + }, + "source": "$ex", + "start": Position { + "column": 27, + "line": 115, + "offset": 2445, + }, + }, + "name": "ex", + }, + ], + }, + }, + Return { + "expr": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 20, + "line": 120, + "offset": 2605, + }, + "source": "new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt()", + "start": Position { + "column": 16, + "line": 116, + "offset": 2488, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 18, + "line": 120, + "offset": 2603, + }, + "source": "new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt", + "start": Position { + "column": 16, + "line": 116, + "offset": 2488, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 18, + "line": 120, + "offset": 2603, + }, + "source": "goatIt", + "start": Position { + "column": 12, + "line": 120, + "offset": 2597, + }, + }, + "name": "goatIt", + }, + "what": New { + "arguments": [], + "kind": "new", + "loc": Location { + "end": Position { + "column": 9, + "line": 120, + "offset": 2594, + }, + "source": "new class extends fooBar { + function goatIt() { + return "meeeh"; + } + }", + "start": Position { + "column": 16, + "line": 116, + "offset": 2488, + }, + }, + "parenthesizedExpression": true, + "what": Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 26, + "line": 118, + "offset": 2571, + }, + "source": ""meeeh"", + "start": Position { + "column": 19, + "line": 118, + "offset": 2564, + }, + }, + "raw": ""meeeh"", + "unicode": false, + "value": "meeeh", + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 27, + "line": 118, + "offset": 2572, + }, + "source": "return "meeeh";", + "start": Position { + "column": 12, + "line": 118, + "offset": 2557, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 11, + "line": 119, + "offset": 2584, + }, + "source": "{ + return "meeeh"; + }", + "start": Position { + "column": 28, + "line": 117, + "offset": 2543, + }, + }, + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 11, + "line": 119, + "offset": 2584, + }, + "source": "function goatIt()", + "start": Position { + "column": 10, + "line": 117, + "offset": 2525, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 25, + "line": 117, + "offset": 2540, + }, + "source": "goatIt", + "start": Position { + "column": 19, + "line": 117, + "offset": 2534, + }, + }, + "name": "goatIt", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 40, + "line": 116, + "offset": 2512, + }, + "source": "fooBar", + "start": Position { + "column": 34, + "line": 116, + "offset": 2506, + }, + }, + "name": "fooBar", + "resolution": "uqn", + }, + "implements": null, + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 9, + "line": 120, + "offset": 2594, + }, + "source": "class extends fooBar { + function goatIt() { + return "meeeh"; + } + }", + "start": Position { + "column": 20, + "line": 116, + "offset": 2492, + }, + }, + "name": null, + }, + }, + }, + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 21, + "line": 120, + "offset": 2606, + }, + "source": "return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt();", + "start": Position { + "column": 8, + "line": 116, + "offset": 2480, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 7, + "line": 121, + "offset": 2614, + }, + "source": "{ + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + }", + "start": Position { + "column": 16, + "line": 114, + "offset": 2416, + }, + }, + }, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 15, + "line": 110, + "offset": 2274, + }, + "source": "$bipbip", + "start": Position { + "column": 8, + "line": 110, + "offset": 2267, + }, + }, + "name": "bipbip", + }, + "loc": Location { + "end": Position { + "column": 35, + "line": 110, + "offset": 2294, + }, + "source": "$bipbip = clone $something;", + "start": Position { + "column": 8, + "line": 110, + "offset": 2267, + }, + }, + "operator": "=", + "right": Clone { + "kind": "clone", + "loc": Location { + "end": Position { + "column": 34, + "line": 110, + "offset": 2293, + }, + "source": "clone $something", + "start": Position { + "column": 18, + "line": 110, + "offset": 2277, + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 34, + "line": 110, + "offset": 2293, + }, + "source": "$something", + "start": Position { + "column": 24, + "line": 110, + "offset": 2283, + }, + }, + "name": "something", + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 35, + "line": 110, + "offset": 2294, + }, + "source": "$bipbip = clone $something;", + "start": Position { + "column": 8, + "line": 110, + "offset": 2267, + }, + }, + }, + ExpressionStatement { + "expression": Call { + "arguments": [ + Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 33, + "line": 111, + "offset": 2328, + }, + "source": "1", + "start": Position { + "column": 32, + "line": 111, + "offset": 2327, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 33, + "line": 111, + "offset": 2328, + }, + "source": "1", + "start": Position { + "column": 32, + "line": 111, + "offset": 2327, + }, + }, + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 36, + "line": 111, + "offset": 2331, + }, + "source": "2", + "start": Position { + "column": 35, + "line": 111, + "offset": 2330, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 36, + "line": 111, + "offset": 2331, + }, + "source": "2", + "start": Position { + "column": 35, + "line": 111, + "offset": 2330, + }, + }, + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 39, + "line": 111, + "offset": 2334, + }, + "source": "3", + "start": Position { + "column": 38, + "line": 111, + "offset": 2333, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 39, + "line": 111, + "offset": 2334, + }, + "source": "3", + "start": Position { + "column": 38, + "line": 111, + "offset": 2333, + }, + }, + "value": "3", + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 40, + "line": 111, + "offset": 2335, + }, + "source": "[1, 2, 3]", + "start": Position { + "column": 31, + "line": 111, + "offset": 2326, + }, + }, + "shortForm": true, + }, + ], + "kind": "call", + "loc": Location { + "end": Position { + "column": 42, + "line": 111, + "offset": 2337, + }, + "source": "$bipbip->crazy()->boom([1, 2, 3]);", + "start": Position { + "column": 8, + "line": 111, + "offset": 2303, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 30, + "line": 111, + "offset": 2325, + }, + "source": "$bipbip->crazy()->boom", + "start": Position { + "column": 8, + "line": 111, + "offset": 2303, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 30, + "line": 111, + "offset": 2325, + }, + "source": "boom", + "start": Position { + "column": 26, + "line": 111, + "offset": 2321, + }, + }, + "name": "boom", + }, + "what": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 24, + "line": 111, + "offset": 2319, + }, + "source": "$bipbip->crazy()", + "start": Position { + "column": 8, + "line": 111, + "offset": 2303, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 22, + "line": 111, + "offset": 2317, + }, + "source": "$bipbip->crazy", + "start": Position { + "column": 8, + "line": 111, + "offset": 2303, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 22, + "line": 111, + "offset": 2317, + }, + "source": "crazy", + "start": Position { + "column": 17, + "line": 111, + "offset": 2312, + }, + }, + "name": "crazy", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 15, + "line": 111, + "offset": 2310, + }, + "source": "$bipbip", + "start": Position { + "column": 8, + "line": 111, + "offset": 2303, + }, + }, + "name": "bipbip", + }, + }, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 42, + "line": 111, + "offset": 2337, + }, + "source": "$bipbip->crazy()->boom([1, 2, 3]);", + "start": Position { + "column": 8, + "line": 111, + "offset": 2303, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 7, + "line": 112, + "offset": 2345, + }, + "source": "{ + $bipbip = clone $something; + $bipbip->crazy()->boom([1, 2, 3]); + }", + "start": Position { + "column": 10, + "line": 109, + "offset": 2257, + }, + }, + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 31, + "line": 113, + "offset": 2399, + }, + "source": "$ex->printStackTrace();", + "start": Position { + "column": 8, + "line": 113, + "offset": 2376, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 28, + "line": 113, + "offset": 2396, + }, + "source": "$ex->printStackTrace", + "start": Position { + "column": 8, + "line": 113, + "offset": 2376, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 28, + "line": 113, + "offset": 2396, + }, + "source": "printStackTrace", + "start": Position { + "column": 13, + "line": 113, + "offset": 2381, + }, + }, + "name": "printStackTrace", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 11, + "line": 113, + "offset": 2379, + }, + "source": "$ex", + "start": Position { + "column": 8, + "line": 113, + "offset": 2376, + }, + }, + "name": "ex", + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 31, + "line": 113, + "offset": 2399, + }, + "source": "$ex->printStackTrace();", + "start": Position { + "column": 8, + "line": 113, + "offset": 2376, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 7, + "line": 114, + "offset": 2407, + }, + "source": "{ + $ex->printStackTrace(); + }", + "start": Position { + "column": 28, + "line": 112, + "offset": 2366, + }, + }, + }, + "kind": "catch", + "loc": Location { + "end": Position { + "column": 7, + "line": 114, + "offset": 2407, + }, + "source": "catch(Coco|Nut $ex) { + $ex->printStackTrace(); + }", + "start": Position { + "column": 8, + "line": 112, + "offset": 2346, + }, + }, + "variable": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 26, + "line": 112, + "offset": 2364, + }, + "source": "$ex", + "start": Position { + "column": 23, + "line": 112, + "offset": 2361, + }, + }, + "name": "ex", + }, + "what": [ + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 18, + "line": 112, + "offset": 2356, + }, + "source": "Coco", + "start": Position { + "column": 14, + "line": 112, + "offset": 2352, + }, + }, + "name": "Coco", + "resolution": "uqn", + }, + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 22, + "line": 112, + "offset": 2360, + }, + "source": "Nut", + "start": Position { + "column": 19, + "line": 112, + "offset": 2357, + }, + }, + "name": "Nut", + "resolution": "uqn", + }, + ], + }, + ], + "kind": "try", + "loc": Location { + "end": Position { + "column": 7, + "line": 121, + "offset": 2614, + }, + "source": "try { + $bipbip = clone $something; + $bipbip->crazy()->boom([1, 2, 3]); + } catch(Coco|Nut $ex) { + $ex->printStackTrace(); + } finally { + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + }", + "start": Position { + "column": 6, + "line": 109, + "offset": 2253, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 5, + "line": 122, + "offset": 2620, + }, + "source": "{ + try { + $bipbip = clone $something; + $bipbip->crazy()->boom([1, 2, 3]); + } catch(Coco|Nut $ex) { + $ex->printStackTrace(); + } finally { + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + } + }", + "start": Position { + "column": 48, + "line": 108, + "offset": 2245, + }, + }, + }, + "kind": "if", + "loc": Location { + "end": Position { + "column": 5, + "line": 129, + "offset": 2837, + }, + "source": "if (!($something instanceof Banana)) { + try { + $bipbip = clone $something; + $bipbip->crazy()->boom([1, 2, 3]); + } catch(Coco|Nut $ex) { + $ex->printStackTrace(); + } finally { + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + } + } else { + for($i = 0; $i < count($this->banana); $i++) { + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + } + // @todo $this->a_$foo + return $$foo ?? false; + }", + "start": Position { + "column": 11, + "line": 108, + "offset": 2208, + }, + }, + "shortForm": false, + "test": Unary { + "kind": "unary", + "loc": Location { + "end": Position { + "column": 46, + "line": 108, + "offset": 2243, + }, + "source": "!($something instanceof Banana)", + "start": Position { + "column": 15, + "line": 108, + "offset": 2212, + }, + }, + "type": "!", + "what": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 27, + "line": 108, + "offset": 2224, + }, + "source": "$something", + "start": Position { + "column": 17, + "line": 108, + "offset": 2214, + }, + }, + "name": "something", + }, + "loc": Location { + "end": Position { + "column": 45, + "line": 108, + "offset": 2242, + }, + "source": "$something instanceof Banana", + "start": Position { + "column": 17, + "line": 108, + "offset": 2214, + }, + }, + "parenthesizedExpression": true, + "right": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 45, + "line": 108, + "offset": 2242, + }, + "source": "Banana", + "start": Position { + "column": 39, + "line": 108, + "offset": 2236, + }, + }, + "name": "Banana", + "resolution": "uqn", + }, + "type": "instanceof", + }, + }, + }, + "body": Block { + "children": [ + While { + "body": Block { + "children": [ + If { + "alternate": Continue { + "kind": "continue", + "level": null, + "loc": Location { + "end": Position { + "column": 24, + "line": 101, + "offset": 2103, + }, + "source": "continue;", + "start": Position { + "column": 15, + "line": 101, + "offset": 2094, + }, + }, + }, + "body": Block { + "children": [ + Break { + "kind": "break", + "level": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 19, + "line": 100, + "offset": 2077, + }, + "source": "foo", + "start": Position { + "column": 16, + "line": 100, + "offset": 2074, + }, + }, + "name": "foo", + "resolution": "uqn", + }, + "loc": Location { + "end": Position { + "column": 20, + "line": 100, + "offset": 2078, + }, + "source": "break foo;", + "start": Position { + "column": 10, + "line": 100, + "offset": 2068, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 9, + "line": 101, + "offset": 2088, + }, + "source": "{ + break foo; + }", + "start": Position { + "column": 50, + "line": 99, + "offset": 2056, + }, + }, + }, + "kind": "if", + "loc": Location { + "end": Position { + "column": 24, + "line": 101, + "offset": 2103, + }, + "source": "if ((int)calculateMeaningOfLife() === 42) { + break foo; + } else continue;", + "start": Position { + "column": 8, + "line": 99, + "offset": 2014, + }, + }, + "shortForm": false, + "test": Bin { + "kind": "bin", + "left": Cast { + "expr": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 41, + "line": 99, + "offset": 2047, + }, + "source": "calculateMeaningOfLife()", + "start": Position { + "column": 17, + "line": 99, + "offset": 2023, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 39, + "line": 99, + "offset": 2045, + }, + "source": "calculateMeaningOfLife", + "start": Position { + "column": 17, + "line": 99, + "offset": 2023, + }, + }, + "name": "calculateMeaningOfLife", + "resolution": "uqn", + }, + }, + "kind": "cast", + "loc": Location { + "end": Position { + "column": 41, + "line": 99, + "offset": 2047, + }, + "source": "(int)calculateMeaningOfLife()", + "start": Position { + "column": 12, + "line": 99, + "offset": 2018, + }, + }, + "raw": "(int)", + "type": "int", + }, + "loc": Location { + "end": Position { + "column": 48, + "line": 99, + "offset": 2054, + }, + "source": "(int)calculateMeaningOfLife() === 42", + "start": Position { + "column": 12, + "line": 99, + "offset": 2018, + }, + }, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 48, + "line": 99, + "offset": 2054, + }, + "source": "42", + "start": Position { + "column": 46, + "line": 99, + "offset": 2052, + }, + }, + "value": "42", + }, + "type": "===", + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 7, + "line": 102, + "offset": 2111, + }, + "source": "{ + if ((int)calculateMeaningOfLife() === 42) { + break foo; + } else continue; + }", + "start": Position { + "column": 18, + "line": 98, + "offset": 2004, + }, + }, + }, + "kind": "while", + "loc": Location { + "end": Position { + "column": 7, + "line": 102, + "offset": 2111, + }, + "source": "while($bar) { + if ((int)calculateMeaningOfLife() === 42) { + break foo; + } else continue; + }", + "start": Position { + "column": 6, + "line": 98, + "offset": 1992, + }, + }, + "shortForm": false, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 16, + "line": 98, + "offset": 2002, + }, + "source": "$bar", + "start": Position { + "column": 12, + "line": 98, + "offset": 1998, + }, + }, + "name": "bar", + }, + }, + Do { + "body": Block { + "children": [ + Inline { + "kind": "inline", + "loc": Location { + "end": Position { + "column": 8, + "line": 106, + "offset": 2169, + }, + "source": " Caesar: here I was + ", + "start": Position { + "column": 0, + "line": 105, + "offset": 2134, + }, + }, + "raw": " + Caesar: here I was + ", + "value": " Caesar: here I was + ", + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 7, + "line": 107, + "offset": 2182, + }, + "source": "{ + ?> + Caesar: here I was + + Caesar: here I was + + Caesar: here I was + fooBar::NUMBAR) { + while($bar) { + if ((int)calculateMeaningOfLife() === 42) { + break foo; + } else continue; + } + do { + ?> + Caesar: here I was + crazy()->boom([1, 2, 3]); + } catch(Coco|Nut $ex) { + $ex->printStackTrace(); + } finally { + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + } + } else { + for($i = 0; $i < count($this->banana); $i++) { + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + } + // @todo $this->a_$foo + return $$foo ?? false; + }", + "start": Position { + "column": 4, + "line": 97, + "offset": 1958, + }, + }, + "shortForm": false, + "test": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 11, + "line": 97, + "offset": 1965, + }, + "source": "$bar", + "start": Position { + "column": 7, + "line": 97, + "offset": 1961, + }, + }, + "name": "bar", + }, + "loc": Location { + "end": Position { + "column": 28, + "line": 97, + "offset": 1982, + }, + "source": "$bar > fooBar::NUMBAR", + "start": Position { + "column": 7, + "line": 97, + "offset": 1961, + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "loc": Location { + "end": Position { + "column": 28, + "line": 97, + "offset": 1982, + }, + "source": "fooBar::NUMBAR", + "start": Position { + "column": 14, + "line": 97, + "offset": 1968, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 28, + "line": 97, + "offset": 1982, + }, + "source": "NUMBAR", + "start": Position { + "column": 22, + "line": 97, + "offset": 1976, + }, + }, + "name": "NUMBAR", + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 20, + "line": 97, + "offset": 1974, + }, + "source": "fooBar", + "start": Position { + "column": 14, + "line": 97, + "offset": 1968, + }, + }, + "name": "fooBar", + "resolution": "uqn", + }, + }, + "type": ">", + }, + }, + Return { + "expr": Empty { + "expression": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 33, + "line": 130, + "offset": 2871, + }, + "source": "namespace\\FOOBAR", + "start": Position { + "column": 17, + "line": 130, + "offset": 2855, + }, + }, + "name": "FOOBAR", + "resolution": "rn", + }, + "kind": "empty", + "loc": Location { + "end": Position { + "column": 34, + "line": 130, + "offset": 2872, + }, + "source": "empty(namespace\\FOOBAR)", + "start": Position { + "column": 11, + "line": 130, + "offset": 2849, + }, + }, + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 35, + "line": 130, + "offset": 2873, + }, + "source": "return empty(namespace\\FOOBAR);", + "start": Position { + "column": 4, + "line": 130, + "offset": 2842, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 3, + "line": 131, + "offset": 2877, + }, + "source": "{ + static $banana; + if($bar > fooBar::NUMBAR) { + while($bar) { + if ((int)calculateMeaningOfLife() === 42) { + break foo; + } else continue; + } + do { + ?> + Caesar: here I was + crazy()->boom([1, 2, 3]); + } catch(Coco|Nut $ex) { + $ex->printStackTrace(); + } finally { + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + } + } else { + for($i = 0; $i < count($this->banana); $i++) { + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + } + // @todo $this->a_$foo + return $$foo ?? false; + } + return empty(namespace\\FOOBAR); + }", + "start": Position { + "column": 57, + "line": 95, + "offset": 1932, + }, + }, + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "loc": Location { + "end": Position { + "column": 3, + "line": 131, + "offset": 2877, + }, + "source": "function(?int $bar = 42) use($something) : bool", + "start": Position { + "column": 9, + "line": 95, + "offset": 1884, + }, + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 56, + "line": 95, + "offset": 1931, + }, + "source": "bool", + "start": Position { + "column": 52, + "line": 95, + "offset": 1927, + }, + }, + "name": "bool", + "raw": "bool", + }, + "uses": [ + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 48, + "line": 95, + "offset": 1923, + }, + "source": "$something", + "start": Position { + "column": 38, + "line": 95, + "offset": 1913, + }, + }, + "name": "something", + }, + ], + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 4, + "line": 131, + "offset": 2878, + }, + "source": "$foo = function(?int $bar = 42) use($something) : bool { + static $banana; + if($bar > fooBar::NUMBAR) { + while($bar) { + if ((int)calculateMeaningOfLife() === 42) { + break foo; + } else continue; + } + do { + ?> + Caesar: here I was + crazy()->boom([1, 2, 3]); + } catch(Coco|Nut $ex) { + $ex->printStackTrace(); + } finally { + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + } + } else { + for($i = 0; $i < count($this->banana); $i++) { + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + } + // @todo $this->a_$foo + return $$foo ?? false; + } + return empty(namespace\\FOOBAR); + };", + "start": Position { + "column": 2, + "line": 95, + "offset": 1877, + }, + }, + }, + If { + "alternate": If { + "alternate": null, + "body": Block { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "loc": Location { + "end": Position { + "column": 20, + "line": 136, + "offset": 2947, + }, + "source": "\`ls -larth\`", + "start": Position { + "column": 9, + "line": 136, + "offset": 2936, + }, + }, + "raw": "\`ls -larth\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 19, + "line": 136, + "offset": 2946, + }, + "source": "ls -larth", + "start": Position { + "column": 10, + "line": 136, + "offset": 2937, + }, + }, + "raw": "ls -larth", + "unicode": false, + "value": "ls -larth", + }, + "kind": "encapsedpart", + "loc": Location { + "end": Position { + "column": 19, + "line": 136, + "offset": 2946, + }, + "source": "ls -larth", + "start": Position { + "column": 10, + "line": 136, + "offset": 2937, + }, + }, + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 21, + "line": 136, + "offset": 2948, + }, + "source": "echo \`ls -larth\`;", + "start": Position { + "column": 4, + "line": 136, + "offset": 2931, + }, + }, + "shortForm": false, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 21, + "line": 136, + "offset": 2948, + }, + "source": "echo \`ls -larth\`;", + "start": Position { + "column": 4, + "line": 136, + "offset": 2931, + }, + }, + }, + "kind": "if", + "loc": Location { + "end": Position { + "column": 21, + "line": 136, + "offset": 2948, + }, + "source": "elseif ($bar): + echo \`ls -larth\`;", + "start": Position { + "column": 2, + "line": 135, + "offset": 2912, + }, + }, + "shortForm": true, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 14, + "line": 135, + "offset": 2924, + }, + "source": "$bar", + "start": Position { + "column": 10, + "line": 135, + "offset": 2920, + }, + }, + "name": "bar", + }, + }, + "body": Block { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "loc": Location { + "end": Position { + "column": 15, + "line": 134, + "offset": 2908, + }, + "source": "\`bar&\`", + "start": Position { + "column": 9, + "line": 134, + "offset": 2902, + }, + }, + "raw": "\`bar&\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 14, + "line": 134, + "offset": 2907, + }, + "source": "bar&", + "start": Position { + "column": 10, + "line": 134, + "offset": 2903, + }, + }, + "raw": "bar&", + "unicode": false, + "value": "bar&", + }, + "kind": "encapsedpart", + "loc": Location { + "end": Position { + "column": 14, + "line": 134, + "offset": 2907, + }, + "source": "bar&", + "start": Position { + "column": 10, + "line": 134, + "offset": 2903, + }, + }, + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 16, + "line": 134, + "offset": 2909, + }, + "source": "echo \`bar&\`;", + "start": Position { + "column": 4, + "line": 134, + "offset": 2897, + }, + }, + "shortForm": false, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 21, + "line": 136, + "offset": 2948, + }, + "source": "echo \`bar&\`; + elseif ($bar): + echo \`ls -larth\`;", + "start": Position { + "column": 4, + "line": 134, + "offset": 2897, + }, + }, + }, + "kind": "if", + "loc": Location { + "end": Position { + "column": 8, + "line": 137, + "offset": 2957, + }, + "source": "if ($foo): + echo \`bar&\`; + elseif ($bar): + echo \`ls -larth\`; + endif;", + "start": Position { + "column": 2, + "line": 133, + "offset": 2882, + }, + }, + "shortForm": true, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 133, + "offset": 2890, + }, + "source": "$foo", + "start": Position { + "column": 6, + "line": 133, + "offset": 2886, + }, + }, + "name": "foo", + }, + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": List { + "items": [ + Noop { + "kind": "noop", + "loc": Location { + "end": Position { + "column": 7, + "line": 140, + "offset": 2984, + }, + "source": "", + "start": Position { + "column": 7, + "line": 140, + "offset": 2984, + }, + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 10, + "line": 140, + "offset": 2987, + }, + "source": "$a", + "start": Position { + "column": 8, + "line": 140, + "offset": 2985, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 140, + "offset": 2987, + }, + "source": "$a", + "start": Position { + "column": 8, + "line": 140, + "offset": 2985, + }, + }, + "name": "a", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 24, + "line": 140, + "offset": 3001, + }, + "source": "list($b, $c)", + "start": Position { + "column": 12, + "line": 140, + "offset": 2989, + }, + }, + "unpack": false, + "value": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 19, + "line": 140, + "offset": 2996, + }, + "source": "$b", + "start": Position { + "column": 17, + "line": 140, + "offset": 2994, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 140, + "offset": 2996, + }, + "source": "$b", + "start": Position { + "column": 17, + "line": 140, + "offset": 2994, + }, + }, + "name": "b", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 23, + "line": 140, + "offset": 3000, + }, + "source": "$c", + "start": Position { + "column": 21, + "line": 140, + "offset": 2998, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 23, + "line": 140, + "offset": 3000, + }, + "source": "$c", + "start": Position { + "column": 21, + "line": 140, + "offset": 2998, + }, + }, + "name": "c", + }, + }, + ], + "kind": "list", + "loc": Location { + "end": Position { + "column": 24, + "line": 140, + "offset": 3001, + }, + "source": "list($b, $c)", + "start": Position { + "column": 12, + "line": 140, + "offset": 2989, + }, + }, + "shortForm": false, + }, + }, + ], + "kind": "list", + "loc": Location { + "end": Position { + "column": 25, + "line": 140, + "offset": 3002, + }, + "source": "list(,$a, list($b, $c))", + "start": Position { + "column": 2, + "line": 140, + "offset": 2979, + }, + }, + "shortForm": false, + }, + "loc": Location { + "end": Position { + "column": 40, + "line": 140, + "offset": 3017, + }, + "source": "list(,$a, list($b, $c)) = [1, [2, 3]];", + "start": Position { + "column": 2, + "line": 140, + "offset": 2979, + }, + }, + "operator": "=", + "right": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 30, + "line": 140, + "offset": 3007, + }, + "source": "1", + "start": Position { + "column": 29, + "line": 140, + "offset": 3006, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 30, + "line": 140, + "offset": 3007, + }, + "source": "1", + "start": Position { + "column": 29, + "line": 140, + "offset": 3006, + }, + }, + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 38, + "line": 140, + "offset": 3015, + }, + "source": "[2, 3]", + "start": Position { + "column": 32, + "line": 140, + "offset": 3009, + }, + }, + "unpack": false, + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 34, + "line": 140, + "offset": 3011, + }, + "source": "2", + "start": Position { + "column": 33, + "line": 140, + "offset": 3010, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 34, + "line": 140, + "offset": 3011, + }, + "source": "2", + "start": Position { + "column": 33, + "line": 140, + "offset": 3010, + }, + }, + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 37, + "line": 140, + "offset": 3014, + }, + "source": "3", + "start": Position { + "column": 36, + "line": 140, + "offset": 3013, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 37, + "line": 140, + "offset": 3014, + }, + "source": "3", + "start": Position { + "column": 36, + "line": 140, + "offset": 3013, + }, + }, + "value": "3", + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 38, + "line": 140, + "offset": 3015, + }, + "source": "[2, 3]", + "start": Position { + "column": 32, + "line": 140, + "offset": 3009, + }, + }, + "shortForm": true, + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 39, + "line": 140, + "offset": 3016, + }, + "source": "[1, [2, 3]]", + "start": Position { + "column": 28, + "line": 140, + "offset": 3005, + }, + }, + "shortForm": true, + }, + }, + "kind": "expressionstatement", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 140, + "offset": 2977, + }, + "source": "// list version +", + "start": Position { + "column": 2, + "line": 139, + "offset": 2961, + }, + }, + "offset": 2961, + "value": "// list version +", + }, + ], + "loc": Location { + "end": Position { + "column": 40, + "line": 140, + "offset": 3017, + }, + "source": "list(,$a, list($b, $c)) = [1, [2, 3]];", + "start": Position { + "column": 2, + "line": 140, + "offset": 2979, + }, + }, + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": List { + "items": [ + Noop { + "kind": "noop", + "loc": Location { + "end": Position { + "column": 3, + "line": 141, + "offset": 3021, + }, + "source": "", + "start": Position { + "column": 3, + "line": 141, + "offset": 3021, + }, + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 6, + "line": 141, + "offset": 3024, + }, + "source": "$a", + "start": Position { + "column": 4, + "line": 141, + "offset": 3022, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 6, + "line": 141, + "offset": 3024, + }, + "source": "$a", + "start": Position { + "column": 4, + "line": 141, + "offset": 3022, + }, + }, + "name": "a", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 16, + "line": 141, + "offset": 3034, + }, + "source": "[$b, ,$c]", + "start": Position { + "column": 7, + "line": 141, + "offset": 3025, + }, + }, + "unpack": false, + "value": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 10, + "line": 141, + "offset": 3028, + }, + "source": "$b", + "start": Position { + "column": 8, + "line": 141, + "offset": 3026, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 141, + "offset": 3028, + }, + "source": "$b", + "start": Position { + "column": 8, + "line": 141, + "offset": 3026, + }, + }, + "name": "b", + }, + }, + Noop { + "kind": "noop", + "loc": Location { + "end": Position { + "column": 11, + "line": 141, + "offset": 3029, + }, + "source": " ", + "start": Position { + "column": 12, + "line": 141, + "offset": 3030, + }, + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 15, + "line": 141, + "offset": 3033, + }, + "source": "$c", + "start": Position { + "column": 13, + "line": 141, + "offset": 3031, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 15, + "line": 141, + "offset": 3033, + }, + "source": "$c", + "start": Position { + "column": 13, + "line": 141, + "offset": 3031, + }, + }, + "name": "c", + }, + }, + ], + "kind": "list", + "loc": Location { + "end": Position { + "column": 16, + "line": 141, + "offset": 3034, + }, + "source": "[$b, ,$c]", + "start": Position { + "column": 7, + "line": 141, + "offset": 3025, + }, + }, + "shortForm": true, + }, + }, + ], + "kind": "list", + "loc": Location { + "end": Position { + "column": 17, + "line": 141, + "offset": 3035, + }, + "source": "[,$a,[$b, ,$c]]", + "start": Position { + "column": 2, + "line": 141, + "offset": 3020, + }, + }, + "shortForm": true, + }, + "loc": Location { + "end": Position { + "column": 23, + "line": 141, + "offset": 3041, + }, + "source": "[,$a,[$b, ,$c]] = $f;", + "start": Position { + "column": 2, + "line": 141, + "offset": 3020, + }, + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 22, + "line": 141, + "offset": 3040, + }, + "source": "$f", + "start": Position { + "column": 20, + "line": 141, + "offset": 3038, + }, + }, + "name": "f", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 23, + "line": 141, + "offset": 3041, + }, + "source": "[,$a,[$b, ,$c]] = $f;", + "start": Position { + "column": 2, + "line": 141, + "offset": 3020, + }, + }, + }, + ExpressionStatement { + "expression": Print { + "expression": Encapsed { + "kind": "encapsed", + "label": "BAZ", + "loc": Location { + "end": Position { + "column": 3, + "line": 144, + "offset": 3074, + }, + "source": "<<Hello 'achoum', + 'bashful' => 'tadah' + ]; + /** + * Something is done here + */ + final public function doSomething() { + // do not wanna do + foreach($this->dwarf as $name => $greeting) { + echo "Hey ho $name, $greeting !"; + continue $foo; + } + throw new \\ComeToHome('Thats it'); + } + } + + interface Miror extends Object { + public function Am_I_Uggly() : bool; + protected function broken() : bool; + static protected function isWhiteSnowAlive() : bool; + } + + function iter() { + yield 'ator' => $foo; + yield from iter(50); + } + + trait Line { + public function draw(bool $arrow = false) : string { + switch($this->style) { + case 'dot': + case 'point': + $body = '......'; + break; + default: + $body = '-----'; + break; + } + return $body . ($arrow ? '>' : ''); + } + private function shuut() { + return __NAMESPACE__; + } + } + + // this is SPARTA ! + function sparta() : ?int { + global $persians; + + $index = -1; +next: + $guy = $persians[++$index]; + if(rand(0, 10)>5 || false) { + @$guy->kill(); + } else { + $guy->kick(...$foo); + } + if ((int)$index < count($persians)) goto next; + + return 300 | 5; + } + + $foo = function(?int $bar = 42) use($something) : bool { + static $banana; + if($bar > fooBar::NUMBAR) { + while($bar) { + if ((int)calculateMeaningOfLife() === 42) { + break foo; + } else continue; + } + do { + ?> + Caesar: here I was + crazy()->boom([1, 2, 3]); + } catch(Coco|Nut $ex) { + $ex->printStackTrace(); + } finally { + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + } + } else { + for($i = 0; $i < count($this->banana); $i++) { + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + } + // @todo $this->a_$foo + return $$foo ?? false; + } + return empty(namespace\\FOOBAR); + }; + + if ($foo): + echo \`bar&\`; + elseif ($bar): + echo \`ls -larth\`; + endif; + + // list version + list(,$a, list($b, $c)) = [1, [2, 3]]; + [,$a,[$b, ,$c]] = $f; + print(<<a_$foo +", + "start": Position { + "column": 6, + "line": 127, + "offset": 2780, + }, + }, + "offset": 2780, + "value": "// @todo $this->a_$foo +", + }, + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 140, + "offset": 2977, + }, + "source": "// list version +", + "start": Position { + "column": 2, + "line": 139, + "offset": 2961, + }, + }, + "offset": 2961, + "value": "// list version +", + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 18, + "line": 156, + "offset": 3191, + }, + "source": "#!/usr/bin/php + +Hello 'achoum', + 'bashful' => 'tadah' + ]; + /** + * Something is done here + */ + final public function doSomething() { + // do not wanna do + foreach($this->dwarf as $name => $greeting) { + echo "Hey ho $name, $greeting !"; + continue $foo; + } + throw new \\ComeToHome('Thats it'); + } + } + + interface Miror extends Object { + public function Am_I_Uggly() : bool; + protected function broken() : bool; + static protected function isWhiteSnowAlive() : bool; + } + + function iter() { + yield 'ator' => $foo; + yield from iter(50); + } + + trait Line { + public function draw(bool $arrow = false) : string { + switch($this->style) { + case 'dot': + case 'point': + $body = '......'; + break; + default: + $body = '-----'; + break; + } + return $body . ($arrow ? '>' : ''); + } + private function shuut() { + return __NAMESPACE__; + } + } + + // this is SPARTA ! + function sparta() : ?int { + global $persians; + + $index = -1; +next: + $guy = $persians[++$index]; + if(rand(0, 10)>5 || false) { + @$guy->kill(); + } else { + $guy->kick(...$foo); + } + if ((int)$index < count($persians)) goto next; + + return 300 | 5; + } + + $foo = function(?int $bar = 42) use($something) : bool { + static $banana; + if($bar > fooBar::NUMBAR) { + while($bar) { + if ((int)calculateMeaningOfLife() === 42) { + break foo; + } else continue; + } + do { + ?> + Caesar: here I was + crazy()->boom([1, 2, 3]); + } catch(Coco|Nut $ex) { + $ex->printStackTrace(); + } finally { + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + } + } else { + for($i = 0; $i < count($this->banana); $i++) { + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + } + // @todo $this->a_$foo + return $$foo ?? false; + } + return empty(namespace\\FOOBAR); + }; + + if ($foo): + echo \`bar&\`; + elseif ($bar): + echo \`ls -larth\`; + endif; + + // list version + list(,$a, list($b, $c)) = [1, [2, 3]]; + [,$a,[$b, ,$c]] = $f; + print(<<' (T_DOUBLE_ARROW), expecting ';' on line 1", + "token": "'=>' (T_DOUBLE_ARROW)", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '=>' (T_DOUBLE_ARROW) on line 1", + "token": "'=>' (T_DOUBLE_ARROW)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '$x' (T_VARIABLE), expecting ';' on line 1", + "token": "'$x' (T_VARIABLE)", + }, + ], + "kind": "program", +} +`; + +exports[`arrow function error / empty not allowed 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": undefined, + "byref": false, + "isStatic": false, + "kind": "arrowfunc", + "nullable": false, + "type": null, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected ';' on line 1", + "token": "';'", + }, + ], + "kind": "program", +} +`; + +exports[`arrow function error / fn fails on php7.4 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "arg", + }, + "kind": "return", + }, + ], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [ + Error { + "expected": "(", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'fn' (T_FN), expecting '(' on line 1", + "token": "'fn' (T_FN)", + }, + ], + "kind": "program", +} +`; + +exports[`arrow function error / fn passes on php7.3 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "arg", + }, + "kind": "return", + }, + ], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "fn", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`arrow function inside call 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Variable { + "curly": false, + "kind": "variable", + "name": "arg", + }, + "byref": false, + "isStatic": false, + "kind": "arrowfunc", + "nullable": false, + "type": null, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`arrow function return type 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + "byref": false, + "isStatic": false, + "kind": "arrowfunc", + "nullable": true, + "type": TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`arrow function simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + "byref": false, + "isStatic": false, + "kind": "arrowfunc", + "nullable": false, + "type": null, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/assign.test.js.snap b/test/snapshot/__snapshots__/assign.test.js.snap new file mode 100644 index 000000000..69241ab07 --- /dev/null +++ b/test/snapshot/__snapshots__/assign.test.js.snap @@ -0,0 +1,543 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`assign %= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "%=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign &= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "&=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign **= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "**=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign *= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "*=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign += 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "+=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign .= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": ".=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign /= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "/=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign <<= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "<<=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign >>= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": ">>=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign ??= (php < 7) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": RetIf { + "falseExpr": undefined, + "kind": "retif", + "test": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "trueExpr": undefined, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '?' on line 1", + "token": "'?'", + }, + Error { + "expected": ":", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '=', expecting ':' on line 1", + "token": "'='", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '=' on line 1", + "token": "'='", + }, + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '$var' (T_VARIABLE), expecting ';' on line 1", + "token": "'$var' (T_VARIABLE)", + }, + ], + "kind": "program", +} +`; + +exports[`assign ??= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "??=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign ??= with bin 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "??=", + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Number { + "kind": "number", + "value": "10", + }, + "type": "+", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign ^= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "^=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign |= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "|=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign -= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "-=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign multiple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`assign with ref 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/ast.test.js.snap b/test/snapshot/__snapshots__/ast.test.js.snap new file mode 100644 index 000000000..91208a884 --- /dev/null +++ b/test/snapshot/__snapshots__/ast.test.js.snap @@ -0,0 +1,655 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test AST structure #176 - lost \`?>\` in program node 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "loc": Location { + "end": Position { + "column": 12, + "line": 2, + "offset": 18, + }, + "source": "__LINE__", + "start": Position { + "column": 4, + "line": 2, + "offset": 10, + }, + }, + "raw": "__LINE__", + "value": "__LINE__", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 12, + "line": 2, + "offset": 18, + }, + "source": "__LINE__", + "start": Position { + "column": 4, + "line": 2, + "offset": 10, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 6, + "line": 3, + "offset": 25, + }, + "source": "", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test AST structure fix #120 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'World'", + "unicode": false, + "value": "World", + }, + ], + "kind": "echo", + "shortForm": false, + }, + Inline { + "kind": "inline", + "raw": " + !", + "value": " !", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure fix #127 - echo statements 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""hello"", + "unicode": false, + "value": "hello", + }, + ], + "kind": "echo", + "shortForm": false, + }, + Inline { + "kind": "inline", + "raw": " world", + "value": " world", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure fix #127 - inline 1`] = ` +Program { + "children": [ + Inline { + "kind": "inline", + "raw": "?>?>", + "value": "?>?>", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure fix #370 - classreference instead identifier(classreferent) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Name { + "kind": "name", + "name": "test", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure fix #370 - nullkeyword 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": NullKeyword { + "kind": "nullkeyword", + "raw": "Null", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test clone 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Clone { + "kind": "clone", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test coalesce operator 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + "type": "??", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test constants 1`] = ` +Program { + "children": [ + ConstantStatement { + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "value": Number { + "kind": "number", + "value": "3.14", + }, + }, + ], + "kind": "constantstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test die/exit 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bye"", + "unicode": false, + "value": "bye", + }, + "kind": "exit", + "useDie": true, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Exit { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Number { + "kind": "number", + "value": "1", + }, + }, + "kind": "exit", + "useDie": false, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test echo, isset, unset, empty 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + RetIf { + "falseExpr": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""ko"", + "unicode": false, + "value": "ko", + }, + "kind": "retif", + "test": Variable { + "curly": false, + "kind": "variable", + "name": "expr", + "parenthesizedExpression": true, + }, + "trueExpr": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""ok"", + "unicode": false, + "value": "ok", + }, + }, + ], + "kind": "echo", + "shortForm": false, + }, + ExpressionStatement { + "expression": Print { + "expression": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""some text"", + "unicode": false, + "value": "some text", + }, + "kind": "print", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Isset { + "kind": "isset", + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + ], + }, + "kind": "expressionstatement", + }, + Unset { + "kind": "unset", + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + }, + ExpressionStatement { + "expression": Empty { + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "empty", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test eval 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Eval { + "kind": "eval", + "source": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""return true;"", + "unicode": false, + "value": "return true;", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test include / require 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Include { + "kind": "include", + "once": false, + "require": false, + "target": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""file.php"", + "unicode": false, + "value": "file.php", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Include { + "kind": "include", + "once": true, + "require": false, + "target": Bin { + "kind": "bin", + "left": Name { + "kind": "name", + "name": "PATH", + "resolution": "uqn", + }, + "parenthesizedExpression": true, + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""/file.php"", + "unicode": false, + "value": "/file.php", + }, + "type": ".", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Include { + "kind": "include", + "once": false, + "require": true, + "target": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""req.php"", + "unicode": false, + "value": "req.php", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Include { + "kind": "include", + "once": true, + "require": true, + "target": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""file.php"", + "unicode": false, + "value": "file.php", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test inline 1`] = ` +Program { + "children": [ + Inline { + "kind": "inline", + "raw": "Hello ", + "value": "Hello ", + }, + Echo { + "expressions": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'World'", + "unicode": false, + "value": "World", + }, + ], + "kind": "echo", + "shortForm": false, + }, + Inline { + "kind": "inline", + "raw": " + !", + "value": " !", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test invalid namespace separator 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Error { + "expected": "SCALAR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '\\' (T_NS_SEPARATOR) on line 1", + "token": "'\\' (T_NS_SEPARATOR)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1", + }, + }, + "kind": "expressionstatement", + }, + Inline { + "kind": "inline", + "raw": " + !", + "value": " !", + }, + ], + "errors": [ + Error { + "expected": "SCALAR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '\\' (T_NS_SEPARATOR) on line 1", + "token": "'\\' (T_NS_SEPARATOR)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '$var' (T_VARIABLE), expecting ';' on line 1", + "token": "'$var' (T_VARIABLE)", + }, + ], + "kind": "program", +} +`; + +exports[`Test AST structure test magics 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Magic { + "kind": "magic", + "raw": "__FILE__", + "value": "__FILE__", + }, + Magic { + "kind": "magic", + "raw": "__DIR__", + "value": "__DIR__", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test program 1`] = ` +Program { + "children": [], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test shell 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": "\`ls -larth\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "ls -larth", + "unicode": false, + "value": "ls -larth", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test AST structure test syntax error 1`] = `"Parse Error : syntax error, unexpected '$b' (T_VARIABLE), expecting ';' on line 3"`; diff --git a/test/snapshot/__snapshots__/attributes.test.js.snap b/test/snapshot/__snapshots__/attributes.test.js.snap new file mode 100644 index 000000000..36fb1d4f0 --- /dev/null +++ b/test/snapshot/__snapshots__/attributes.test.js.snap @@ -0,0 +1,2692 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Parse Attributes can parse anon-class attributes 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": New { + "arguments": [], + "kind": "new", + "what": Class { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "T", + }, + ], + "kind": "attrgroup", + }, + ], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": null, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse anonymous function attributes 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "Pure", + }, + ], + "kind": "attrgroup", + }, + ], + "body": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + "byref": false, + "isStatic": false, + "kind": "arrowfunc", + "nullable": false, + "type": null, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "A", + }, + ], + "kind": "attrgroup", + }, + ], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse attributes in inner statements 1`] = ` +Program { + "children": [ + Namespace { + "children": [ + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Closure { + "arguments": [], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "C", + }, + ], + "kind": "attrgroup", + }, + ], + "body": Closure { + "arguments": [], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "Pure", + }, + ], + "kind": "attrgroup", + }, + ], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [], + }, + "byref": false, + "isStatic": false, + "kind": "arrowfunc", + "nullable": false, + "type": null, + }, + "kind": "return", + }, + ], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "type": null, + }, + ], + "kind": "namespace", + "name": "A", + "withBrackets": true, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse attributes with namespace 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "\\JetBrains\\PhpStorm\\Pure", + }, + ], + "kind": "attrgroup", + }, + ], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse class attributes 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "Deprecated", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""use NewClass"", + "unicode": false, + "value": "use NewClass", + }, + ], + "kind": "attribute", + "name": "replace", + }, + ], + "kind": "attrgroup", + }, + ], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "DepClass", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse class const attributes 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "B", + }, + ], + "kind": "attrgroup", + }, + ], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "B", + }, + "value": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse class property attributes 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "B", + }, + ], + "kind": "attrgroup", + }, + ], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + "value": null, + }, + ], + "visibility": "public", + }, + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "C", + }, + ], + "kind": "attrgroup", + }, + ], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "c", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "C", + "resolution": "uqn", + }, + "value": null, + }, + ], + "visibility": "private", + }, + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "D", + }, + ], + "kind": "attrgroup", + }, + ], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "d", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "protected", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse interface attributes 1`] = ` +Program { + "children": [ + Interface { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "A", + }, + ], + "kind": "attrgroup", + }, + ], + "body": [ + ClassConstant { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "C", + }, + ], + "kind": "attrgroup", + }, + ], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "D", + }, + "value": Number { + "kind": "number", + "value": "0", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "", + }, + Method { + "arguments": [], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "E", + }, + ], + "kind": "attrgroup", + }, + ], + "body": null, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "f", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "kind": "interface", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse method attributes 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "Pure", + }, + ], + "kind": "attrgroup", + }, + ], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "m", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Test", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse multi-line attributes 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "One", + }, + Attribute { + "args": [], + "kind": "attribute", + "name": "Two", + }, + Attribute { + "args": [], + "kind": "attribute", + "name": "Three", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "Four", + }, + ], + "kind": "attrgroup", + }, + ], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Multi", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse param attributes 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "Unsigned", + }, + ], + "kind": "attrgroup", + }, + ], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "n", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "f", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse params with argument labels 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [ + namedargument { + "kind": "namedargument", + "name": "value", + "value": Number { + "kind": "number", + "value": "1234", + }, + }, + ], + "kind": "attribute", + "name": "MyAttribute", + }, + ], + "kind": "attrgroup", + }, + ], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse params with bitwise operations 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "type": "|", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att2", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att2", + "resolution": "uqn", + }, + }, + "type": "&", + }, + ], + "kind": "attribute", + "name": "Att2", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att3", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att3", + "resolution": "uqn", + }, + }, + "type": "^", + }, + ], + "kind": "attribute", + "name": "Att3", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Unary { + "kind": "unary", + "type": "~", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att4", + "resolution": "uqn", + }, + }, + }, + ], + "kind": "attribute", + "name": "Att4", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att5", + "resolution": "uqn", + }, + }, + "right": Number { + "kind": "number", + "value": "1", + }, + "type": ">>", + }, + ], + "kind": "attribute", + "name": "Att5", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att6", + "resolution": "uqn", + }, + }, + "right": Number { + "kind": "number", + "value": "1", + }, + "type": "<<", + }, + ], + "kind": "attribute", + "name": "Att6", + }, + ], + "kind": "attrgroup", + }, + ], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + }, + ], + "comments": [], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse params with comments 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "Unsigned", + }, + ], + "kind": "attrgroup", + }, + ], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 26, + "value": "/* Pure */", + }, + ], + "name": "Pure", + }, + ], + "kind": "attrgroup", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 0, + "value": "// Line 1 +", + }, + ], + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 66, + "value": "// Try using b +", + }, + ], + "name": "Deprecated", + }, + ], + "kind": "attrgroup", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 43, + "value": "// Line 3 +", + }, + ], + }, + ], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "type": null, + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 0, + "value": "// Line 1 +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 26, + "value": "/* Pure */", + }, + CommentLine { + "kind": "commentline", + "offset": 43, + "value": "// Line 3 +", + }, + CommentLine { + "kind": "commentline", + "offset": 66, + "value": "// Try using b +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse params with end characters 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""])}>"", + "unicode": false, + "value": "])}>", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + ], + "kind": "attribute", + "name": "End", + }, + ], + "kind": "attrgroup", + }, + ], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "End", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse params with logical operations 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "type": "||", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att2", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att2", + "resolution": "uqn", + }, + }, + "type": "&&", + }, + ], + "kind": "attribute", + "name": "Att2", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att3", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att3", + "resolution": "uqn", + }, + }, + "type": "or", + }, + ], + "kind": "attribute", + "name": "Att3", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att4", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att4", + "resolution": "uqn", + }, + }, + "type": "and", + }, + ], + "kind": "attribute", + "name": "Att4", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att5", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att5", + "resolution": "uqn", + }, + }, + "type": "xor", + }, + ], + "kind": "attribute", + "name": "Att5", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Unary { + "kind": "unary", + "type": "!", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att6", + "resolution": "uqn", + }, + }, + }, + ], + "kind": "attribute", + "name": "Att6", + }, + ], + "kind": "attrgroup", + }, + ], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + }, + ], + "comments": [], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse params with mathematical expressions 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Unary { + "kind": "unary", + "type": "-", + "what": Number { + "kind": "number", + "value": "20", + }, + }, + "right": Bin { + "kind": "bin", + "left": Unary { + "kind": "unary", + "type": "+", + "what": Number { + "kind": "number", + "value": "10", + }, + }, + "parenthesizedExpression": true, + "right": Number { + "kind": "number", + "value": "5", + }, + "type": "/", + }, + "type": "*", + }, + "right": Number { + "kind": "number", + "value": "2", + }, + "type": "%", + }, + "right": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "8", + }, + "right": Number { + "kind": "number", + "value": "2", + }, + "type": "**", + }, + "type": "+", + }, + "right": Unary { + "kind": "unary", + "type": "+", + "what": Unary { + "kind": "unary", + "type": "-", + "what": Number { + "kind": "number", + "value": "2", + }, + }, + }, + "type": "-", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + ], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + }, + ], + "comments": [], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse params with string concatenation 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""a"", + "unicode": false, + "value": "a", + }, + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""b"", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att2", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""a"", + "unicode": false, + "value": "a", + }, + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""b"", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att2", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'a'", + "unicode": false, + "value": "a", + }, + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""b"", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att2", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'a'", + "unicode": false, + "value": "a", + }, + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""b"", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att2", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""a"", + "unicode": false, + "value": "a", + }, + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'b'", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att2", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""a"", + "unicode": false, + "value": "a", + }, + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'b'", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att2", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'a'", + "unicode": false, + "value": "a", + }, + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'b'", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att2", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'a'", + "unicode": false, + "value": "a", + }, + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'b'", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att2", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""b"", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""b"", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'b'", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'b'", + "unicode": false, + "value": "b", + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""a"", + "unicode": false, + "value": "a", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""a"", + "unicode": false, + "value": "a", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'a'", + "unicode": false, + "value": "a", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'a'", + "unicode": false, + "value": "a", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Bin { + "kind": "bin", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "what": Name { + "kind": "name", + "name": "Att1", + "resolution": "uqn", + }, + }, + "type": ".", + }, + ], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + ], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + }, + ], + "comments": [], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes can parse parms with array values 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [ + Array { + "items": [ + Entry { + "byRef": false, + "key": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""a"", + "unicode": false, + "value": "a", + }, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'b'", + "unicode": false, + "value": "b", + }, + "kind": "entry", + "unpack": false, + "value": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "class", + }, + "what": Name { + "kind": "name", + "name": "Test", + "resolution": "uqn", + }, + }, + }, + Entry { + "byRef": false, + "key": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'c'", + "unicode": false, + "value": "c", + }, + "kind": "entry", + "unpack": false, + "value": Array { + "items": [], + "kind": "array", + "shortForm": true, + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + ], + "kind": "attribute", + "name": "List", + }, + ], + "kind": "attrgroup", + }, + ], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes doesnt parse attributes for assignments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1", + }, + }, + "kind": "expressionstatement", + }, + ], + "comments": [], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes doesnt repeat attributes from previous function 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [], + "kind": "attribute", + "name": "Att1", + }, + ], + "kind": "attrgroup", + }, + ], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "c", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "d", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes parses attributes as comments for PHP < 8 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 45, + "value": "#[Att2] +", + }, + ], + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 9, + "value": "#[Att1] +", + }, + ], + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 9, + "value": "#[Att1] +", + }, + CommentLine { + "kind": "commentline", + "offset": 45, + "value": "#[Att2] +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Parse Attributes parses this complicated edge case 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "Assert", + }, + "kind": "useitem", + "name": "Symfony\\Component\\Validator\\Constraints", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": null, + }, + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [ + AttrGroup { + "attrs": [ + Attribute { + "args": [ + namedargument { + "kind": "namedargument", + "name": "allowNull", + "value": Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + }, + namedargument { + "kind": "namedargument", + "name": "groups", + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'foo'", + "unicode": false, + "value": "foo", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + }, + ], + "kind": "attribute", + "name": "Assert\\NotBlank", + }, + Attribute { + "args": [ + namedargument { + "kind": "namedargument", + "name": "max", + "value": Number { + "kind": "number", + "value": "255", + }, + }, + namedargument { + "kind": "namedargument", + "name": "groups", + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'foo'", + "unicode": false, + "value": "foo", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + }, + ], + "kind": "attribute", + "name": "Assert\\Length", + }, + ], + "kind": "attrgroup", + }, + ], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "value", + }, + "nullable": true, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + "value": NullKeyword { + "kind": "nullkeyword", + "raw": "null", + }, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "ValueModel", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/bin.test.js.snap b/test/snapshot/__snapshots__/bin.test.js.snap new file mode 100644 index 000000000..859c2ea69 --- /dev/null +++ b/test/snapshot/__snapshots__/bin.test.js.snap @@ -0,0 +1,1197 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`bin != 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "!=", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin !== 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "!==", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin % 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "%", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin & 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "&", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin && 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "&&", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin * 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "*", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin ** 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "**", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin ** right-associative 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "c", + }, + "type": "**", + }, + "type": "**", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin + 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "+", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin . 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": ".", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin / 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "/", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin < 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "<", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin << 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "<<", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin <= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "<=", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin <=> 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "<=>", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin == 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "==", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin === 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "===", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin > 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": ">", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin >= 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": ">=", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin >> 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": ">>", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin ?? (php < 7) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": RetIf { + "falseExpr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "retif", + "test": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "trueExpr": undefined, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '?' on line 1", + "token": "'?'", + }, + Error { + "expected": ":", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '$var' (T_VARIABLE), expecting ':' on line 1", + "token": "'$var' (T_VARIABLE)", + }, + ], + "kind": "program", +} +`; + +exports[`bin ?? 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "??", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin ?? right-associative 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "c", + }, + "type": "??", + }, + "type": "??", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin ^ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "^", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin | 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "|", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin || 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "||", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin - 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "-", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin and 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "and", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin assign 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "type": "+", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin instanceof 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Name { + "kind": "name", + "name": "MyClass", + "resolution": "uqn", + }, + "type": "instanceof", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin instanceof parent 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + "type": "instanceof", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin instanceof self 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + "type": "instanceof", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin instanceof static 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": StaticReference { + "kind": "staticreference", + "raw": "static", + }, + "type": "instanceof", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin instanceof variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "type": "instanceof", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin multiple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "type": "+", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "type": "+", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin multiple instanceof static 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": StaticReference { + "kind": "staticreference", + "raw": "static", + }, + "type": "instanceof", + }, + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "right": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + "type": "instanceof", + }, + "type": "&&", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin or 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "or", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin parens 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "parenthesizedExpression": true, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "type": "+", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin parens around \`and\` 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "parenthesizedExpression": true, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "type": "and", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin parens around \`or\` 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "parenthesizedExpression": true, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "type": "or", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin parens around \`xor\` 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "parenthesizedExpression": true, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "type": "xor", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`bin xor 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "xor", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/block.test.js.snap b/test/snapshot/__snapshots__/block.test.js.snap new file mode 100644 index 000000000..6554522b6 --- /dev/null +++ b/test/snapshot/__snapshots__/block.test.js.snap @@ -0,0 +1,940 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`block check empty php blocks 1`] = ` +Program { + "children": [ + Inline { + "kind": "inline", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 8, + "value": "/** + * Comment header + */", + }, + ], + "raw": " +SOME HTML OUTPUT +", + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 64, + "value": "/* Inner comment */", + }, + ], + "value": "SOME HTML OUTPUT +", + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 8, + "value": "/** + * Comment header + */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 64, + "value": "/* Inner comment */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block check empty php file 1`] = ` +Program { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 8, + "value": "/** + * Comment header + */", + }, + ], + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 8, + "value": "/** + * Comment header + */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty class block 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 12, + "value": "/* 1 */", + }, + ], + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 12, + "value": "/* 1 */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty declare block 1`] = ` +Program { + "children": [ + Declare { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 18, + "value": "/* 1 */", + }, + ], + }, + ], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "name": "tick", + }, + "kind": "declaredirective", + "value": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "kind": "declare", + "mode": "block", + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 18, + "value": "/* 1 */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty declare short form 1`] = ` +Program { + "children": [ + Declare { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 17, + "value": "/* 1 */", + }, + ], + }, + ], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "name": "tick", + }, + "kind": "declaredirective", + "value": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "kind": "declare", + "mode": "short", + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 17, + "value": "/* 1 */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty for 1`] = ` +Program { + "children": [ + For { + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 10, + "value": "/* foo */", + }, + ], + }, + ], + "kind": "block", + }, + "increment": [], + "init": [], + "kind": "for", + "shortForm": false, + "test": [], + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 10, + "value": "/* foo */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty for short form 1`] = ` +Program { + "children": [ + For { + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 10, + "value": "/* foo */", + }, + ], + }, + ], + "kind": "block", + }, + "increment": [], + "init": [], + "kind": "for", + "shortForm": true, + "test": [], + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 10, + "value": "/* foo */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty foreach 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 24, + "value": "/* foo */", + }, + ], + }, + ], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 24, + "value": "/* foo */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty foreach short form 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 23, + "value": "/* foo */", + }, + ], + }, + ], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": true, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 23, + "value": "/* foo */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty function block 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 17, + "value": "/* 1 */", + }, + ], + }, + ], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 17, + "value": "/* 1 */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty if #2 short form 1`] = ` +Program { + "children": [ + If { + "alternate": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 10, + "value": "/* pre */", + }, + ], + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 24, + "value": "/* inner */", + }, + ], + }, + "kind": "if", + "shortForm": true, + "test": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 43, + "value": "/* out */", + }, + ], + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 10, + "value": "/* pre */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 24, + "value": "/* inner */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 43, + "value": "/* out */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty if #3 short form 1`] = ` +Program { + "children": [ + If { + "alternate": If { + "alternate": Block { + "children": [], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 50, + "value": "/* bar */", + }, + ], + }, + "body": Block { + "children": [], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 34, + "value": "/* baz */", + }, + ], + }, + "kind": "if", + "shortForm": true, + "test": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + "body": Block { + "children": [], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 10, + "value": "/* foo */", + }, + ], + }, + "kind": "if", + "shortForm": true, + "test": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 10, + "value": "/* foo */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 34, + "value": "/* baz */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 50, + "value": "/* bar */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty if 1`] = ` +Program { + "children": [ + If { + "alternate": null, + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 11, + "value": "/* foo */", + }, + ], + }, + ], + "kind": "block", + }, + "kind": "if", + "shortForm": false, + "test": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 11, + "value": "/* foo */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty if short form 1`] = ` +Program { + "children": [ + If { + "alternate": null, + "body": Block { + "children": [], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 10, + "value": "/* foo */", + }, + ], + }, + "kind": "if", + "shortForm": true, + "test": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 10, + "value": "/* foo */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty method block 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 30, + "value": "/* 1 */", + }, + ], + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "bar", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 30, + "value": "/* 1 */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty namespace block 1`] = ` +Program { + "children": [ + Namespace { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 16, + "value": "/* 1 */", + }, + ], + }, + ], + "kind": "namespace", + "name": "foo", + "withBrackets": true, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 16, + "value": "/* 1 */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty statement 1`] = ` +Program { + "children": [], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 0, + "value": "/* 1 */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 9, + "value": "/* 2 */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 20, + "value": "/* 3 */", + }, + ], + "errors": [], + "kind": "program", + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 0, + "value": "/* 1 */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 9, + "value": "/* 2 */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 20, + "value": "/* 3 */", + }, + ], +} +`; + +exports[`block empty switch 1`] = ` +Program { + "children": [ + Switch { + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 15, + "value": "/* foo */", + }, + ], + }, + ], + "kind": "block", + }, + "kind": "switch", + "shortForm": false, + "test": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 15, + "value": "/* foo */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty switch case short form 1`] = ` +Program { + "children": [ + Switch { + "body": Block { + "children": [ + Case { + "body": Block { + "children": [], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 22, + "value": "/* foo */", + }, + ], + }, + "kind": "case", + "test": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "kind": "block", + }, + "kind": "switch", + "shortForm": true, + "test": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 22, + "value": "/* foo */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block empty switch short form 1`] = ` +Program { + "children": [ + Switch { + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 14, + "value": "/* foo */", + }, + ], + }, + ], + "kind": "block", + }, + "kind": "switch", + "shortForm": true, + "test": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 14, + "value": "/* foo */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`block single 1`] = ` +Program { + "children": [ + Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + ], + "comments": [], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/boolean.test.js.snap b/test/snapshot/__snapshots__/boolean.test.js.snap new file mode 100644 index 000000000..b629ed3ee --- /dev/null +++ b/test/snapshot/__snapshots__/boolean.test.js.snap @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`boolean assign (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`boolean assign 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/break.test.js.snap b/test/snapshot/__snapshots__/break.test.js.snap new file mode 100644 index 000000000..7855e22f8 --- /dev/null +++ b/test/snapshot/__snapshots__/break.test.js.snap @@ -0,0 +1,117 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`break argument 0 1`] = ` +Program { + "children": [ + Break { + "kind": "break", + "level": Number { + "kind": "number", + "value": "0", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`break argument 1 1`] = ` +Program { + "children": [ + Break { + "kind": "break", + "level": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`break argument 2 1`] = ` +Program { + "children": [ + Break { + "kind": "break", + "level": Number { + "kind": "number", + "value": "2", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`break should fail when no ';' at end 1`] = ` +Program { + "children": [ + Break { + "kind": "break", + "level": undefined, + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`break simple 1`] = ` +Program { + "children": [ + Break { + "kind": "break", + "level": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`break with expression 1`] = ` +Program { + "children": [ + Break { + "kind": "break", + "level": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`break with parens 1`] = ` +Program { + "children": [ + Break { + "kind": "break", + "level": Number { + "kind": "number", + "parenthesizedExpression": true, + "value": "1", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/buffer.test.js.snap b/test/snapshot/__snapshots__/buffer.test.js.snap new file mode 100644 index 000000000..44e8a8139 --- /dev/null +++ b/test/snapshot/__snapshots__/buffer.test.js.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test buffers handles buffers as input 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""test"", + "unicode": false, + "value": "test", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/byref.test.js.snap b/test/snapshot/__snapshots__/byref.test.js.snap new file mode 100644 index 000000000..90966c843 --- /dev/null +++ b/test/snapshot/__snapshots__/byref.test.js.snap @@ -0,0 +1,1004 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`byref call result 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Call { + "arguments": [ + Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "b", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref callable variable #2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref callable variable #3 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref callable variable #4 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref callable variable #5 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Name { + "kind": "name", + "name": "CONSTANT", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref callable variable #6 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref callable variable #7 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "test", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref callable variable #8 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref callable variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref closure 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "message", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref foreach (key/value) 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [], + "kind": "block", + }, + "key": Variable { + "curly": false, + "kind": "variable", + "name": "key", + }, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "arr", + }, + "value": Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "val", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref foreach 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "arr", + }, + "value": Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "value", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref function definition 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": true, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "bar", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": true, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref new class 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref offset lookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "bar", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref propertylookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "test", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref return statement 1`] = ` +Program { + "children": [ + Return { + "expr": Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "foo", + }, + "kind": "return", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref static lookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref staticlookup #2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref staticlookup #3 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + }, + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref staticlookup #4 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref staticlookup #5 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref staticlookup #6 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref staticlookup #7 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "getElementByPath", + }, + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref staticlookup #8 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "getElementByPath", + }, + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref staticlookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref variadic 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": true, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "var", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": true, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref with bin #2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + "right": Number { + "kind": "number", + "value": "1", + }, + "type": "+", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`byref with bin 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "type": "||", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/call.test.js.snap b/test/snapshot/__snapshots__/call.test.js.snap new file mode 100644 index 000000000..3cb9f66b4 --- /dev/null +++ b/test/snapshot/__snapshots__/call.test.js.snap @@ -0,0 +1,1759 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test call array 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Foo"", + "unicode": false, + "value": "Foo", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + }, + ], + "kind": "array", + "shortForm": false, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call array parens 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Foo"", + "unicode": false, + "value": "Foo", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + }, + ], + "kind": "array", + "parenthesizedExpression": true, + "shortForm": false, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call comments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 10, + "value": "// comment +", + }, + ], + "unpack": false, + "value": Number { + "kind": "number", + "value": "100", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "0", + }, + }, + ], + "kind": "array", + "shortForm": false, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 10, + "value": "// comment +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call doesnt confused static methods with named arguments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": Name { + "kind": "name", + "name": "a", + "resolution": "uqn", + }, + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call handles spread operator at call site 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + variadic { + "kind": "variadic", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + variadic { + "kind": "variadic", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "baz", + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [ + variadic { + "kind": "variadic", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + variadic { + "kind": "variadic", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "baz", + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside offsetlookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""offset"", + "unicode": false, + "value": "offset", + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside propertylookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup (3) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup (4) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup (5) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup (6) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup (7) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup (8) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""property"", + "unicode": false, + "value": "property", + }, + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup (9) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup (10) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Name { + "kind": "name", + "name": "Order", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup (11) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Literal { + "kind": "literal", + "value": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + }, + "what": Name { + "kind": "name", + "name": "Order", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call inside staticlookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call keyword as named argument 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + namedargument { + "kind": "namedargument", + "name": "array", + "value": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call mix of unnamed and named arguments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Number { + "kind": "number", + "value": "50", + }, + namedargument { + "kind": "namedargument", + "name": "num", + "value": Number { + "kind": "number", + "value": "100", + }, + }, + namedargument { + "kind": "namedargument", + "name": "start_index", + "value": Number { + "kind": "number", + "value": "0", + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call multiple (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call multiple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Call { + "arguments": [], + "kind": "call", + "what": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call multiple arguments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "c", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call named arguments in php 8.0 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + namedargument { + "kind": "namedargument", + "name": "a", + "value": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call nested 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Call { + "arguments": [ + Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call nullsafepropertylookup (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call nullsafepropertylookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call offsetlookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""index"", + "unicode": false, + "value": "index", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call parent 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call propertylookup (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call propertylookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call self 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call single argument 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call static 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": StaticReference { + "kind": "staticreference", + "raw": "static", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call staticlookup (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call staticlookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call string 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": String { + "isDoubleQuote": true, + "kind": "string", + "parenthesizedExpression": true, + "raw": ""func"", + "unicode": false, + "value": "func", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call trailing comma #2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""method"", + "unicode": false, + "value": "method", + }, + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + ], + "kind": "call", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call trailing comma #3 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""method"", + "unicode": false, + "value": "method", + }, + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + ], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call trailing comma 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""method"", + "unicode": false, + "value": "method", + }, + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call variable function (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "func", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call variable function (3) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "func", + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test call variable function 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "func", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/class.test.js.snap b/test/snapshot/__snapshots__/class.test.js.snap new file mode 100644 index 000000000..068548dfe --- /dev/null +++ b/test/snapshot/__snapshots__/class.test.js.snap @@ -0,0 +1,2115 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test classes 8.4 allow new without parenthesis 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "People", + "resolution": "uqn", + }, + }, + "right": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "name", + "resolution": "uqn", + }, + }, + "type": "->", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes Advanced tests 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + TraitUse { + "adaptations": null, + "kind": "traituse", + "traits": [ + Name { + "kind": "name", + "name": "A", + "resolution": "uqn", + }, + ], + }, + TraitUse { + "adaptations": [ + TraitAlias { + "as": Identifier { + "kind": "identifier", + "name": "bar", + }, + "kind": "traitalias", + "method": "foo", + "trait": null, + "visibility": "", + }, + ], + "kind": "traituse", + "traits": [ + Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + ], + }, + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 87, + "value": "// comment +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 106, + "value": "/* boo */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 124, + "value": "/** doc + * data + foo + */", + }, + ], + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "var", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + ], + "visibility": null, + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": true, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "__construct", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "boo", + }, + "nullable": false, + "type": null, + "visibility": "private", + }, + ], + "extends": null, + "implements": [ + Name { + "kind": "name", + "name": "boo", + "resolution": "uqn", + }, + ], + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + Interface { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + "value": Number { + "kind": "number", + "value": "1.5", + }, + }, + ], + "final": false, + "kind": "classconstant", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 332, + "value": "// some doc +", + }, + ], + "nullable": false, + "type": null, + "visibility": "", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": null, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 375, + "value": "/** foo */", + }, + ], + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + "visibility": "protected", + }, + ], + "extends": [ + Name { + "kind": "name", + "name": "something", + "resolution": "uqn", + }, + ], + "kind": "interface", + "name": Identifier { + "kind": "identifier", + "name": "boo", + }, + }, + Trait { + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + "value": Number { + "kind": "number", + "value": "1.5", + }, + }, + ], + "final": false, + "kind": "classconstant", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 455, + "value": "// some doc +", + }, + ], + "nullable": false, + "type": null, + "visibility": "", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": null, + "byref": false, + "isAbstract": true, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + "visibility": "protected", + }, + ], + "kind": "trait", + "name": Identifier { + "kind": "identifier", + "name": "line", + }, + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 87, + "value": "// comment +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 106, + "value": "/* boo */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 124, + "value": "/** doc + * data + foo + */", + }, + CommentLine { + "kind": "commentline", + "offset": 332, + "value": "// some doc +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 375, + "value": "/** foo */", + }, + CommentLine { + "kind": "commentline", + "offset": 455, + "value": "// some doc +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes Implement #183 : static keyword as identifier 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "baz", + }, + "what": StaticReference { + "kind": "staticreference", + "raw": "static", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "fooBar", + }, + "what": Name { + "kind": "name", + "name": "A", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "fooBaz", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": true, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes Implement readonly property 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "uid", + }, + "nullable": false, + "readonly": true, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": null, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "User", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes Implement typed_properties_v2 / php74 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "prop", + }, + "nullable": true, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": NullKeyword { + "kind": "nullkeyword", + "raw": "null", + }, + }, + ], + "visibility": "public", + }, + PropertyStatement { + "isStatic": true, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "y", + }, + "nullable": false, + "readonly": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + ], + }, + "value": null, + }, + ], + "visibility": "protected", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Test", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes Test js properties 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": true, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "constructor", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "constructor", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "constructor", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + "operator": "=", + "right": NullKeyword { + "kind": "nullkeyword", + "raw": "null", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "constructor", + }, + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + "operator": "=", + "right": NullKeyword { + "kind": "nullkeyword", + "raw": "null", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "__proto__", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "__proto__", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes Test of silent mode 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + TraitUse { + "adaptations": null, + "kind": "traituse", + "traits": [ + Name { + "kind": "name", + "name": "A", + "resolution": "uqn", + }, + ], + }, + TraitUse { + "adaptations": [ + TraitAlias { + "as": null, + "kind": "traitalias", + "method": "foo", + "trait": null, + "visibility": "", + }, + TraitAlias { + "as": null, + "kind": "traitalias", + "method": "", + "trait": null, + "visibility": "", + }, + ], + "kind": "traituse", + "traits": [ + Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + ], + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, unexpected 'use' (T_USE), expecting ';' on line 4", + "token": "'use' (T_USE)", + }, + Error { + "expected": [ + 119, + 200, + ], + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, unexpected '}' on line 4", + "token": "'}'", + }, + Error { + "expected": ";", + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, unexpected '}', expecting ';' on line 4", + "token": "'}'", + }, + Error { + "expected": 105, + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, unexpected ';', expecting T_STRING on line 4", + "token": "';'", + }, + Error { + "expected": [ + 119, + 200, + ], + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, unexpected ';' on line 4", + "token": "';'", + }, + Error { + "expected": "}", + "kind": "error", + "line": 5, + "message": "Parse Error : syntax error, expecting '}' on line 5", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test classes Test promoted class properties php 8 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 1, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "id", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 4, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "name", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "c", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 2, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "req", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "ServerRequestInterface", + "resolution": "uqn", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "constructor", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "__proto__", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes Test promoted nullable properties php 8 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 1, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "maybe", + }, + "nullable": true, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 4, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "opt", + }, + "nullable": true, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "constructor", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "__proto__", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes Test promoted readonly class properties 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 1, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "id", + }, + "nullable": false, + "readonly": true, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "__construct", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Bob", + }, + }, + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 1, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "id", + }, + "nullable": false, + "readonly": true, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "__construct", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Bob2", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes Test that readonly method parameters are throwing errors 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 1, + "kind": "parameter", + "name": null, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": null, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "id", + }, + "nullable": false, + "readonly": true, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": null, + }, + ], + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Bob", + }, + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": undefined, + "kind": "error", + "line": 3, + "message": "readonly properties can be used only on class constructor on line 3", + "token": undefined, + }, + Error { + "expected": 222, + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected 'readonly' (T_READ_ONLY), expecting T_VARIABLE on line 3", + "token": "'readonly' (T_READ_ONLY)", + }, + Error { + "expected": [ + ",", + ")", + ], + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected 'readonly' (T_READ_ONLY) on line 3", + "token": "'readonly' (T_READ_ONLY)", + }, + Error { + "expected": ")", + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected 'readonly' (T_READ_ONLY), expecting ')' on line 3", + "token": "'readonly' (T_READ_ONLY)", + }, + Error { + "expected": "{", + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected 'readonly' (T_READ_ONLY), expecting '{' on line 3", + "token": "'readonly' (T_READ_ONLY)", + }, + Error { + "expected": [ + ",", + ";", + "=", + ], + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected ')' on line 3", + "token": "')'", + }, + Error { + "expected": ";", + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected ')', expecting ';' on line 3", + "token": "')'", + }, + Error { + "expected": [ + 198, + 222, + 182, + ], + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected '{' on line 3", + "token": "'{'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, unexpected '}' on line 4", + "token": "'}'", + }, + ], + "kind": "program", +} +`; + +exports[`Test classes Validate usual declarations 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "FOO", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""azerty"", + "unicode": false, + "value": "azerty", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "", + }, + PropertyStatement { + "isStatic": true, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "var", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "public", + }, + Method { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "data", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + "value": NullKeyword { + "kind": "nullkeyword", + "raw": "null", + }, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "data", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "data", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "__construct", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "list", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "", + }, + Method { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "list", + }, + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "list", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + "kind": "return", + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "new", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "protected", + }, + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "bar", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "private", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "foobar", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + "implements": [ + Name { + "kind": "name", + "name": "bim", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bam", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "boum", + "resolution": "uqn", + }, + ], + "isAbstract": false, + "isAnonymous": false, + "isFinal": true, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + Class { + "attrGroups": [], + "body": [ + TraitUse { + "adaptations": [ + TraitPrecedence { + "instead": [ + Name { + "kind": "name", + "name": "A", + "resolution": "uqn", + }, + ], + "kind": "traitprecedence", + "method": Identifier { + "kind": "identifier", + "name": "smallTalk", + }, + "trait": Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + }, + TraitPrecedence { + "instead": [ + Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "C", + "resolution": "uqn", + }, + ], + "kind": "traitprecedence", + "method": Identifier { + "kind": "identifier", + "name": "bigTalk", + }, + "trait": Name { + "kind": "name", + "name": "A", + "resolution": "uqn", + }, + }, + TraitAlias { + "as": Identifier { + "kind": "identifier", + "name": "talk", + }, + "kind": "traitalias", + "method": Identifier { + "kind": "identifier", + "name": "bigTalk", + }, + "trait": Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + "visibility": "public", + }, + TraitAlias { + "as": Identifier { + "kind": "identifier", + "name": "talk", + }, + "kind": "traitalias", + "method": Identifier { + "kind": "identifier", + "name": "bigTalk", + }, + "trait": Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + "visibility": "protected", + }, + TraitAlias { + "as": Identifier { + "kind": "identifier", + "name": "talk", + }, + "kind": "traitalias", + "method": Identifier { + "kind": "identifier", + "name": "bigTalk", + }, + "trait": Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + "visibility": "private", + }, + TraitAlias { + "as": Identifier { + "kind": "identifier", + "name": "list", + }, + "kind": "traitalias", + "method": Identifier { + "kind": "identifier", + "name": "new", + }, + "trait": Name { + "kind": "name", + "name": "A", + "resolution": "uqn", + }, + "visibility": "", + }, + TraitAlias { + "as": Identifier { + "kind": "identifier", + "name": "new", + }, + "kind": "traitalias", + "method": Identifier { + "kind": "identifier", + "name": "list", + }, + "trait": null, + "visibility": "", + }, + ], + "kind": "traituse", + "traits": [ + Name { + "kind": "name", + "name": "A", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + ], + }, + Method { + "arguments": [], + "attrGroups": [], + "body": null, + "byref": true, + "isAbstract": true, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + "visibility": "protected", + }, + ], + "extends": null, + "implements": null, + "isAbstract": true, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "bar", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes abstract and final 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "errors": [ + Error { + "expected": 187, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'final' (T_FINAL), expecting T_CLASS on line 1", + "token": "'final' (T_FINAL)", + }, + ], + "kind": "program", +} +`; + +exports[`Test classes class name as identifier 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes empty 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes final and abstract 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "errors": [ + Error { + "expected": 187, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'abstract' (T_ABSTRACT), expecting T_CLASS on line 1", + "token": "'abstract' (T_ABSTRACT)", + }, + ], + "kind": "program", +} +`; + +exports[`Test classes handles property types with a leading \\ 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "baz", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "\\Bar", + "resolution": "fqn", + }, + "value": null, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes new without parenthesis throw errors in PHP < 8.4 1`] = `"New without parenthesis is not allowed before PHP 8.4 on line 1"`; + +exports[`Test classes readonly class in PHP8.2 should support abstract readonly 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": true, + "isAnonymous": false, + "isFinal": false, + "isReadonly": true, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes readonly class in PHP8.2 should support final readonly 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": true, + "isReadonly": true, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes readonly class in PHP8.2 should support readonly 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": true, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes readonly class in PHP8.2 should support readonly abstract 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": true, + "isAnonymous": false, + "isFinal": false, + "isReadonly": true, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test classes readonly class in PHP8.2 should support readonly final 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": true, + "isReadonly": true, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/classconstant.test.js.snap b/test/snapshot/__snapshots__/classconstant.test.js.snap new file mode 100644 index 000000000..743c71381 --- /dev/null +++ b/test/snapshot/__snapshots__/classconstant.test.js.snap @@ -0,0 +1,476 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`classconstant final 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + ], + "final": true, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classconstant multiple 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "OTHER_CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Other hello world!"", + "unicode": false, + "value": "Other hello world!", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classconstant multiple 8.3 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "NAME_1", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "NAME_2", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Other hello world!"", + "unicode": false, + "value": "Other hello world!", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classconstant private 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "private", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classconstant protected 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "protected", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classconstant public 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classconstant simple 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classconstant simple using 8.3 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classconstant type hinted (supported) 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classconstant type hinted (unsupported) 1`] = `"Parse Error : syntax error, unexpected 'CONSTANT' (T_STRING), expecting '=' on line 1"`; diff --git a/test/snapshot/__snapshots__/classreference.test.js.snap b/test/snapshot/__snapshots__/classreference.test.js.snap new file mode 100644 index 000000000..13bf8cf32 --- /dev/null +++ b/test/snapshot/__snapshots__/classreference.test.js.snap @@ -0,0 +1,168 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`classreference argument type (2) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "Foo\\Foo", + "resolution": "qn", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classreference argument type 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classreference call 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classreference constant 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`classreference variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/clone.test.js.snap b/test/snapshot/__snapshots__/clone.test.js.snap new file mode 100644 index 000000000..9bfb63e0d --- /dev/null +++ b/test/snapshot/__snapshots__/clone.test.js.snap @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`clone assign 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Clone { + "kind": "clone", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`clone simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Clone { + "kind": "clone", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/closure.test.js.snap b/test/snapshot/__snapshots__/closure.test.js.snap new file mode 100644 index 000000000..0f802d252 --- /dev/null +++ b/test/snapshot/__snapshots__/closure.test.js.snap @@ -0,0 +1,729 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`closure argument 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`closure argument and use 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "curly": false, + "kind": "variable", + "name": "use", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`closure argument by ref 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": true, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`closure arguments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`closure arguments and uses 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "curly": false, + "kind": "variable", + "name": "use", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "use", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "use", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`closure empty 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`closure inside call 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "arg", + }, + "kind": "return", + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [], + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`closure simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`closure use 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "curly": false, + "kind": "variable", + "name": "message", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`closure use by ref 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "message", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`closure use multiple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "curly": false, + "kind": "variable", + "name": "message", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "message1", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "message2", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/comment.test.js.snap b/test/snapshot/__snapshots__/comment.test.js.snap new file mode 100644 index 000000000..0288dac0c --- /dev/null +++ b/test/snapshot/__snapshots__/comment.test.js.snap @@ -0,0 +1,2122 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test comments issues fix #55 1`] = ` +Program { + "children": [ + If { + "alternate": null, + "body": Block { + "children": [ + If { + "alternate": null, + "body": Block { + "children": [], + "kind": "block", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 51, + "value": "// inner statements +", + }, + ], + }, + "kind": "if", + "shortForm": true, + "test": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + ], + "kind": "block", + "trailingComments": [ + CommentLine { + "kind": "commentline", + "offset": 88, + "value": "// another comment +", + }, + ], + }, + "kind": "if", + "shortForm": true, + "test": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + "trailingComments": [ + CommentLine { + "kind": "commentline", + "offset": 122, + "value": "// 2nd comment +", + }, + ], + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 51, + "value": "// inner statements +", + }, + CommentLine { + "kind": "commentline", + "offset": 88, + "value": "// another comment +", + }, + CommentLine { + "kind": "commentline", + "offset": 122, + "value": "// 2nd comment +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test comments issues fix #126 : new option 1`] = ` +Program { + "children": [ + If { + "alternate": If { + "alternate": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "2", + }, + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 119, + "value": "/* trailing 2 */", + }, + ], + }, + "kind": "expressionstatement", + "trailingComments": [ + CommentLine { + "kind": "commentline", + "offset": 148, + "value": "// trailing assing +", + }, + ], + }, + ], + "kind": "block", + }, + "kind": "if", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 57, + "value": "// Don't parsed :( +", + }, + ], + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + }, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "if", + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + "trailingComments": [ + CommentLine { + "kind": "commentline", + "offset": 185, + "value": "// trailing elseif +", + }, + ], + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 57, + "value": "// Don't parsed :( +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 119, + "value": "/* trailing 2 */", + }, + CommentLine { + "kind": "commentline", + "offset": 148, + "value": "// trailing assing +", + }, + CommentLine { + "kind": "commentline", + "offset": 185, + "value": "// trailing elseif +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test comments issues fix #189 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 30, + "value": "// Comment 1 +", + }, + ], + "left": Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'string1'", + "unicode": false, + "value": "string1", + }, + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'string2'", + "unicode": false, + "value": "string2", + }, + "type": ".", + }, + "right": String { + "isDoubleQuote": false, + "kind": "string", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 61, + "value": "// Comment 2 +", + }, + CommentLine { + "kind": "commentline", + "offset": 80, + "value": "// Comment 3 +", + }, + ], + "raw": "'string3'", + "unicode": false, + "value": "string3", + }, + "type": ".", + }, + }, + "kind": "expressionstatement", + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 30, + "value": "// Comment 1 +", + }, + CommentLine { + "kind": "commentline", + "offset": 61, + "value": "// Comment 2 +", + }, + CommentLine { + "kind": "commentline", + "offset": 80, + "value": "// Comment 3 +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test comments issues fix #193 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 29, + "value": "// Comment Before +", + }, + ], + "offset": Identifier { + "kind": "identifier", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 70, + "value": "// Comment After +", + }, + ], + "name": "each", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 29, + "value": "// Comment Before +", + }, + CommentLine { + "kind": "commentline", + "offset": 70, + "value": "// Comment After +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test comments issues fix #250 : Leading comments are treated as trailing comments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 6, + "line": 3, + "offset": 18, + }, + "source": "foo();", + "start": Position { + "column": 0, + "line": 3, + "offset": 12, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 3, + "line": 3, + "offset": 15, + }, + "source": "foo", + "start": Position { + "column": 0, + "line": 3, + "offset": 12, + }, + }, + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 3, + "offset": 12, + }, + "source": "// leading +", + "start": Position { + "column": 0, + "line": 2, + "offset": 1, + }, + }, + "offset": 1, + "value": "// leading +", + }, + ], + "loc": Location { + "end": Position { + "column": 6, + "line": 3, + "offset": 18, + }, + "source": "foo();", + "start": Position { + "column": 0, + "line": 3, + "offset": 12, + }, + }, + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 19, + "line": 5, + "offset": 45, + }, + "source": "bar() /* inner */ ;", + "start": Position { + "column": 0, + "line": 5, + "offset": 26, + }, + }, + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "loc": Location { + "end": Position { + "column": 17, + "line": 5, + "offset": 43, + }, + "source": "/* inner */", + "start": Position { + "column": 6, + "line": 5, + "offset": 32, + }, + }, + "offset": 32, + "value": "/* inner */", + }, + ], + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 3, + "line": 5, + "offset": 29, + }, + "source": "bar", + "start": Position { + "column": 0, + "line": 5, + "offset": 26, + }, + }, + "name": "bar", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 5, + "offset": 26, + }, + "source": "// bar +", + "start": Position { + "column": 0, + "line": 4, + "offset": 19, + }, + }, + "offset": 19, + "value": "// bar +", + }, + ], + "loc": Location { + "end": Position { + "column": 19, + "line": 5, + "offset": 45, + }, + "source": "bar() /* inner */ ;", + "start": Position { + "column": 0, + "line": 5, + "offset": 26, + }, + }, + "trailingComments": [ + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 7, + "offset": 58, + }, + "source": "// trailing +", + "start": Position { + "column": 0, + "line": 6, + "offset": 46, + }, + }, + "offset": 46, + "value": "// trailing +", + }, + ], + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 3, + "offset": 12, + }, + "source": "// leading +", + "start": Position { + "column": 0, + "line": 2, + "offset": 1, + }, + }, + "offset": 1, + "value": "// leading +", + }, + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 5, + "offset": 26, + }, + "source": "// bar +", + "start": Position { + "column": 0, + "line": 4, + "offset": 19, + }, + }, + "offset": 19, + "value": "// bar +", + }, + CommentBlock { + "kind": "commentblock", + "loc": Location { + "end": Position { + "column": 17, + "line": 5, + "offset": 43, + }, + "source": "/* inner */", + "start": Position { + "column": 6, + "line": 5, + "offset": 32, + }, + }, + "offset": 32, + "value": "/* inner */", + }, + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 7, + "offset": 58, + }, + "source": "// trailing +", + "start": Position { + "column": 0, + "line": 6, + "offset": 46, + }, + }, + "offset": 46, + "value": "// trailing +", + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 8, + "line": 7, + "offset": 66, + }, + "source": " +// leading +foo(); +// bar +bar() /* inner */ ; +// trailing + ", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test comments issues fix #278 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + "kind": "return", + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": true, + "kind": "method", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 51, + "value": "/** + * Description + */", + }, + ], + "name": Identifier { + "kind": "identifier", + "name": "bar", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + "kind": "return", + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": true, + "kind": "method", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 155, + "value": "/** + * Description + */", + }, + ], + "name": Identifier { + "kind": "identifier", + "name": "baz", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + "kind": "return", + }, + ], + "kind": "block", + "trailingComments": [ + CommentLine { + "kind": "commentline", + "offset": 364, + "value": "// true trailing comment +", + }, + ], + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": true, + "kind": "method", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 261, + "value": "/** + * Description + */", + }, + ], + "name": Identifier { + "kind": "identifier", + "name": "woo", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 1, + "value": "/** + * Class description + */", + }, + ], + "name": Identifier { + "kind": "identifier", + "name": "FooClass", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 1, + "value": "/** + * Class description + */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 51, + "value": "/** + * Description + */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 155, + "value": "/** + * Description + */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 261, + "value": "/** + * Description + */", + }, + CommentLine { + "kind": "commentline", + "offset": 364, + "value": "// true trailing comment +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test comments issues fix call comments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Array { + "items": [], + "kind": "array", + "loc": Location { + "end": Position { + "column": 2, + "line": 3, + "offset": 25, + }, + "source": "array // comment +()", + "start": Position { + "column": 5, + "line": 2, + "offset": 6, + }, + }, + "shortForm": false, + }, + ], + "kind": "call", + "loc": Location { + "end": Position { + "column": 4, + "line": 3, + "offset": 27, + }, + "source": "call(array // comment +());", + "start": Position { + "column": 0, + "line": 2, + "offset": 1, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 4, + "line": 2, + "offset": 5, + }, + "source": "call", + "start": Position { + "column": 0, + "line": 2, + "offset": 1, + }, + }, + "name": "call", + "resolution": "uqn", + "trailingComments": [ + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 3, + "offset": 23, + }, + "source": "// comment +", + "start": Position { + "column": 11, + "line": 2, + "offset": 12, + }, + }, + "offset": 12, + "value": "// comment +", + }, + ], + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 4, + "line": 3, + "offset": 27, + }, + "source": "call(array // comment +());", + "start": Position { + "column": 0, + "line": 2, + "offset": 1, + }, + }, + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "loc": Location { + "end": Position { + "column": 0, + "line": 3, + "offset": 23, + }, + "source": "// comment +", + "start": Position { + "column": 11, + "line": 2, + "offset": 12, + }, + }, + "offset": 12, + "value": "// comment +", + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 8, + "line": 4, + "offset": 36, + }, + "source": " +call(array // comment +()); + ", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test comments issues impl #194 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "operator": "=", + "right": Number { + "kind": "number", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 37, + "value": "/* trail foo */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 55, + "value": "/* lead 1 */", + }, + ], + "value": "1", + }, + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 70, + "value": "/* trail 1 */", + }, + ], + }, + "kind": "expressionstatement", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 9, + "value": "// lead assign +", + }, + ], + }, + ExpressionStatement { + "expression": Call { + "arguments": [ + String { + "isDoubleQuote": true, + "kind": "string", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 123, + "value": "/* lead arg */", + }, + ], + "raw": ""arg"", + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 144, + "value": "/* trail arg */", + }, + ], + "unicode": false, + "value": "arg", + }, + ], + "kind": "call", + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 162, + "value": "/* trail call */", + }, + ], + "what": Name { + "kind": "name", + "name": "callback", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 93, + "value": "// lead call +", + }, + ], + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 189, + "value": "/* trail program */", + }, + ], + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 9, + "value": "// lead assign +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 37, + "value": "/* trail foo */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 55, + "value": "/* lead 1 */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 70, + "value": "/* trail 1 */", + }, + CommentLine { + "kind": "commentline", + "offset": 93, + "value": "// lead call +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 123, + "value": "/* lead arg */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 144, + "value": "/* trail arg */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 162, + "value": "/* trail call */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 189, + "value": "/* trail program */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test comments multi line comments test function 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 98, + "value": "/* @var something */", + }, + ], + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "arg", + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 168, + "value": "/* ignore */", + }, + ], + }, + "kind": "return", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 137, + "value": "// inner +", + }, + ], + }, + ], + "kind": "block", + }, + "byref": true, + "kind": "function", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 9, + "value": "/** + * Description + */", + }, + ], + "name": Identifier { + "kind": "identifier", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 65, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 80, + "value": "/* ignore */", + }, + ], + "name": "name", + }, + "nullable": false, + "type": null, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 9, + "value": "/** + * Description + */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 65, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 80, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 98, + "value": "/* @var something */", + }, + CommentLine { + "kind": "commentline", + "offset": 137, + "value": "// inner +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 168, + "value": "/* ignore */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test comments multi line comments test if statements 1`] = ` +Program { + "children": [ + If { + "alternate": If { + "alternate": If { + "alternate": Block { + "children": [], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 351, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 369, + "value": "/* ignore */", + }, + ], + }, + "body": Block { + "children": [], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 284, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 297, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 311, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 324, + "value": "/* ignore */", + }, + ], + }, + "kind": "if", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 231, + "value": "/* ignore */", + }, + ], + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 251, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 265, + "value": "/* ignore */", + }, + ], + "raw": "false", + "value": false, + }, + }, + "body": Block { + "children": [], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 190, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 204, + "value": "/* ignore */", + }, + ], + }, + "kind": "if", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 89, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 107, + "value": "/* ignore */", + }, + CommentLine { + "kind": "commentline", + "offset": 128, + "value": "// else with a inner if single statement : +", + }, + ], + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 61, + "value": "# inner statement +", + }, + ], + }, + ], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 38, + "value": "/* ignore */", + }, + ], + }, + "kind": "if", + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 12, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 26, + "value": "/* */", + }, + ], + "raw": "true", + "value": true, + }, + }, + If { + "alternate": null, + "body": Block { + "children": [], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 415, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 430, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 451, + "value": "/* ignore */", + }, + ], + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 470, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 483, + "value": "/* ignore */", + }, + ], + }, + "kind": "if", + "shortForm": true, + "test": Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 12, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 26, + "value": "/* */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 38, + "value": "/* ignore */", + }, + CommentLine { + "kind": "commentline", + "offset": 61, + "value": "# inner statement +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 89, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 107, + "value": "/* ignore */", + }, + CommentLine { + "kind": "commentline", + "offset": 128, + "value": "// else with a inner if single statement : +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 190, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 204, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 231, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 251, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 265, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 284, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 297, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 311, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 324, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 351, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 369, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 415, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 430, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 451, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 470, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 483, + "value": "/* ignore */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test comments multi line comments test try statements 1`] = ` +Program { + "children": [ + Try { + "always": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 218, + "value": "/* ignore */", + }, + ], + }, + ], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 182, + "value": "/* zz */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 199, + "value": "/* yy */", + }, + ], + }, + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 36, + "value": "# inner statement +", + }, + ], + }, + ], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 13, + "value": "/* ignore */", + }, + ], + }, + "catches": [ + Catch { + "body": Block { + "children": [ + Noop { + "kind": "noop", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 163, + "value": "/* ee */", + }, + ], + }, + ], + "kind": "block", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 134, + "value": "/* bb */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 144, + "value": "/* dd */", + }, + ], + }, + "kind": "catch", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 64, + "value": "/* dd */", + }, + ], + "variable": Variable { + "curly": false, + "kind": "variable", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 122, + "value": "/* aa */", + }, + ], + "name": "e", + }, + "what": [ + Name { + "kind": "name", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 79, + "value": "/* zz */", + }, + ], + "name": "\\Exception", + "resolution": "fqn", + }, + Name { + "kind": "name", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 99, + "value": "/* 1 */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 109, + "value": "/* 2 */", + }, + ], + "name": "\\Foo", + "resolution": "fqn", + }, + ], + }, + ], + "kind": "try", + "trailingComments": [ + CommentLine { + "kind": "commentline", + "offset": 241, + "value": "// end +", + }, + ], + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 13, + "value": "/* ignore */", + }, + CommentLine { + "kind": "commentline", + "offset": 36, + "value": "# inner statement +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 64, + "value": "/* dd */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 79, + "value": "/* zz */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 99, + "value": "/* 1 */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 109, + "value": "/* 2 */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 122, + "value": "/* aa */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 134, + "value": "/* bb */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 144, + "value": "/* dd */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 163, + "value": "/* ee */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 182, + "value": "/* zz */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 199, + "value": "/* yy */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 218, + "value": "/* ignore */", + }, + CommentLine { + "kind": "commentline", + "offset": 241, + "value": "// end +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test comments test classes 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 72, + "value": "/* hehe */", + }, + CommentLine { + "kind": "commentline", + "offset": 94, + "value": "// @var test +", + }, + ], + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "toto", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "protected", + }, + PropertyStatement { + "isStatic": true, + "kind": "propertystatement", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 149, + "value": "// ignored comment +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 177, + "value": "/** @var Class */", + }, + ], + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Number { + "kind": "number", + "value": "123", + }, + }, + ], + "visibility": "public", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 239, + "value": "/** ignored also **/", + }, + CommentBlock { + "kind": "commentblock", + "offset": 269, + "value": "/** + * @return void + */", + }, + ], + "name": Identifier { + "kind": "identifier", + "name": "void", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 7, + "value": "/** + * Description + */", + }, + ], + "name": Identifier { + "kind": "identifier", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 54, + "value": "/* ignore */", + }, + ], + "name": "name", + }, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 7, + "value": "/** + * Description + */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 54, + "value": "/* ignore */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 72, + "value": "/* hehe */", + }, + CommentLine { + "kind": "commentline", + "offset": 94, + "value": "// @var test +", + }, + CommentLine { + "kind": "commentline", + "offset": 149, + "value": "// ignored comment +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 177, + "value": "/** @var Class */", + }, + CommentBlock { + "kind": "commentblock", + "offset": 239, + "value": "/** ignored also **/", + }, + CommentBlock { + "kind": "commentblock", + "offset": 269, + "value": "/** + * @return void + */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test comments test single line comments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "123", + }, + "trailingComments": [ + CommentLine { + "kind": "commentline", + "offset": 65, + "value": "// 123 +", + }, + ], + }, + "kind": "expressionstatement", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 7, + "value": "# some information +", + }, + CommentLine { + "kind": "commentline", + "offset": 32, + "value": "// another line +", + }, + ], + "trailingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 80, + "value": "/* done */", + }, + ], + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 7, + "value": "# some information +", + }, + CommentLine { + "kind": "commentline", + "offset": 32, + "value": "// another line +", + }, + CommentLine { + "kind": "commentline", + "offset": 65, + "value": "// 123 +", + }, + CommentBlock { + "kind": "commentblock", + "offset": 80, + "value": "/* done */", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/constantstatement.test.js.snap b/test/snapshot/__snapshots__/constantstatement.test.js.snap new file mode 100644 index 000000000..294dc9d86 --- /dev/null +++ b/test/snapshot/__snapshots__/constantstatement.test.js.snap @@ -0,0 +1,71 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`constantstatement multiple 1`] = ` +Program { + "children": [ + ConstantStatement { + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "OTHER_CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Other hello world!"", + "unicode": false, + "value": "Other hello world!", + }, + }, + ], + "kind": "constantstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`constantstatement simple 1`] = ` +Program { + "children": [ + ConstantStatement { + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + ], + "kind": "constantstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/continue.test.js.snap b/test/snapshot/__snapshots__/continue.test.js.snap new file mode 100644 index 000000000..7304d2d5f --- /dev/null +++ b/test/snapshot/__snapshots__/continue.test.js.snap @@ -0,0 +1,117 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`continue argument 0 1`] = ` +Program { + "children": [ + Continue { + "kind": "continue", + "level": Number { + "kind": "number", + "value": "0", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`continue argument 1 1`] = ` +Program { + "children": [ + Continue { + "kind": "continue", + "level": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`continue argument 2 1`] = ` +Program { + "children": [ + Continue { + "kind": "continue", + "level": Number { + "kind": "number", + "value": "2", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`continue should fail when no ';' at end 1`] = ` +Program { + "children": [ + Continue { + "kind": "continue", + "level": undefined, + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`continue simple 1`] = ` +Program { + "children": [ + Continue { + "kind": "continue", + "level": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`continue with expression 1`] = ` +Program { + "children": [ + Continue { + "kind": "continue", + "level": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`continue with parens 1`] = ` +Program { + "children": [ + Continue { + "kind": "continue", + "level": Number { + "kind": "number", + "parenthesizedExpression": true, + "value": "1", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/declare.test.js.snap b/test/snapshot/__snapshots__/declare.test.js.snap new file mode 100644 index 000000000..2c5cebf74 --- /dev/null +++ b/test/snapshot/__snapshots__/declare.test.js.snap @@ -0,0 +1,197 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`declare encoding 1`] = ` +Program { + "children": [ + Declare { + "children": [], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "name": "encoding", + }, + "kind": "declaredirective", + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'ISO-8859-1'", + "unicode": false, + "value": "ISO-8859-1", + }, + }, + ], + "kind": "declare", + "mode": "none", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`declare mode short 1`] = ` +Program { + "children": [ + Declare { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "name": "ticks", + }, + "kind": "declaredirective", + "value": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "kind": "declare", + "mode": "short", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`declare multiple 1`] = ` +Program { + "children": [ + Declare { + "children": [], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "name": "A", + }, + "kind": "declaredirective", + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'B'", + "unicode": false, + "value": "B", + }, + }, + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "name": "C", + }, + "kind": "declaredirective", + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'D'", + "unicode": false, + "value": "D", + }, + }, + ], + "kind": "declare", + "mode": "block", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`declare nested 1`] = ` +Program { + "children": [ + Declare { + "children": [], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "name": "ticks", + }, + "kind": "declaredirective", + "value": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "kind": "declare", + "mode": "block", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`declare strict_types 1`] = ` +Program { + "children": [ + Declare { + "children": [], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "name": "strict_types", + }, + "kind": "declaredirective", + "value": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "kind": "declare", + "mode": "none", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`declare ticks 1`] = ` +Program { + "children": [ + Declare { + "children": [], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "name": "ticks", + }, + "kind": "declaredirective", + "value": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "kind": "declare", + "mode": "none", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/echo.test.js.snap b/test/snapshot/__snapshots__/echo.test.js.snap new file mode 100644 index 000000000..8d9553a8b --- /dev/null +++ b/test/snapshot/__snapshots__/echo.test.js.snap @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`echo multiple 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""string"", + "unicode": false, + "value": "string", + }, + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""string"", + "unicode": false, + "value": "string", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`echo simple 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""string"", + "unicode": false, + "value": "string", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/empty.test.js.snap b/test/snapshot/__snapshots__/empty.test.js.snap new file mode 100644 index 000000000..61e4986b7 --- /dev/null +++ b/test/snapshot/__snapshots__/empty.test.js.snap @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`empty assign 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Empty { + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "empty", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`empty simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Empty { + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "empty", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/encapsed.test.js.snap b/test/snapshot/__snapshots__/encapsed.test.js.snap new file mode 100644 index 000000000..743c33a27 --- /dev/null +++ b/test/snapshot/__snapshots__/encapsed.test.js.snap @@ -0,0 +1,3566 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`encapsed curly #2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$$juice} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "juice", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed curly #3 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$call()} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Call { + "arguments": [], + "kind": "call", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "call", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed curly 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$juice} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "juice", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed dollar open curly braces #2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string \${$juice} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "juice", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed dollar open curly braces #3 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string \${\${$juice}} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "juice", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed dollar open curly braces #4 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string \${call()} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed dollar open curly braces #5 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string \${test[test]} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Name { + "kind": "name", + "name": "test", + "resolution": "uqn", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed dollar open curly braces #6 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string \${test[1]} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed dollar open curly braces #7 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string \${test[-1]} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Unary { + "kind": "unary", + "type": "-", + "what": Number { + "kind": "number", + "value": "1", + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed dollar open curly braces #8 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string \${test[$var]} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed dollar open curly braces 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string \${juice} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "juice", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed multiple nullsafepropertylookup (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj?->property?->property} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed multiple propertylookup (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj->property->property} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed negative offset in encapsed var offset 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""$var[-1]"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": -1, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed newline before closing curly (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$var +} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed no curly 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string $$juice string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string $", + "unicode": false, + "value": "string $", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "juice", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed nullsafepropertylookup (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj?->property} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed nullsafepropertylookup (simple syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string $obj?->property string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "?->property string", + "unicode": false, + "value": "?->property string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed nullsafepropertylookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": EncapsedPart { + "curly": false, + "expression": Encapsed { + "kind": "encapsed", + "raw": ""set{$type}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "set", + "unicode": false, + "value": "set", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "type", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed nullsafepropertylookup and offsetlookup (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj?->values[3]?->name} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "name", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "3", + }, + "what": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "values", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed nullsafepropertylookup by variable (2) (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj?->{$array[1]}} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed nullsafepropertylookup by variable (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj?->$var} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed nullsafepropertylookup with comments (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$var?->foo?->bar /* Comment */ } string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed nullsafepropertylookup with multiple call (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj?->call()?->call()} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Call { + "arguments": [], + "kind": "call", + "what": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Call { + "arguments": [], + "kind": "call", + "what": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed offsetlookup (2) (simple syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string $array[koolaid1] string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Identifier { + "kind": "identifier", + "name": "koolaid1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed offsetlookup (3) (simple syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string $array[0][0] string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "0", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "[0] string", + "unicode": false, + "value": "[0] string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed offsetlookup (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$array["key"]} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""key"", + "unicode": false, + "value": "key", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed offsetlookup (simple syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string $array[0] string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "0", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed offsetlookup 2 (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$array[4][3]} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "3", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "4", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed offsetlookup 3 (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$arr[foo][3]} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "3", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "arr", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed offsetlookup 4 (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$arr["foo"][3]} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "3", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""foo"", + "unicode": false, + "value": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "arr", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed positive offset in encapsed var offset 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""$var[1]"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed propertylookup (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj->property} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed propertylookup (simple syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string $obj->property string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed propertylookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": EncapsedPart { + "curly": false, + "expression": Encapsed { + "kind": "encapsed", + "raw": ""set{$type}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "set", + "unicode": false, + "value": "set", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "type", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed propertylookup by variable (2) (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj->{$array[1]}} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed propertylookup by variable (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj->$var} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed propertylookup with comments (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$var->foo->bar /* Comment */ } string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed propertylookup with multiple call (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj->call()->call()} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed staticlookup (2) (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj::call()} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed staticlookup (3) (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj::$var::$var} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed staticlookup (4) (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$var::$target::$resource::$binary::$foo::$bar::$foobar::$bar::$foo::$foobar::$bar::$foo} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "foobar", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "foobar", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "binary", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "resource", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "target", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed staticlookup (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$obj::$var} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed string offset in encapsed var offset 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""$var[var]"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Identifier { + "kind": "identifier", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed string offset in encapsed var offset 2`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""$var[$var]"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed two variable (simple syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string $var->$var string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "->", + "unicode": false, + "value": "->", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed value of the var (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {\${$name}} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "name", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed value of the var named by the return value (2) (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {\${call()}} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": true, + "kind": "variable", + "name": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed value of the var named by the return value (3) (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {\${$obj->property}} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": true, + "kind": "variable", + "name": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed value of the var named by the return value (4) (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {\${$obj->call()}} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": true, + "kind": "variable", + "name": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed value of the var named by the return value (5) (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {\${$obj::$var}} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": true, + "kind": "variable", + "name": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed value of the var named by the return value (6) (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {\${$obj::call()}} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": true, + "kind": "variable", + "name": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed value of the var named by the return value (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {\${call()}} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": true, + "kind": "variable", + "name": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed variable (complex syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$var} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed variable (simple syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string $var string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed variable curly (simple syntax) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string \${var} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed variable with before closing curly 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string {$var } string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`encapsed variable with space opening before curly 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""string { $var} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string { ", + "unicode": false, + "value": "string { ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "} string", + "unicode": false, + "value": "} string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/enum.test.js.snap b/test/snapshot/__snapshots__/enum.test.js.snap new file mode 100644 index 000000000..0d32779aa --- /dev/null +++ b/test/snapshot/__snapshots__/enum.test.js.snap @@ -0,0 +1,589 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test enums can alias cases 1`] = ` +Program { + "children": [ + Enum { + "attrGroups": [], + "body": [ + EnumCase { + "kind": "enumcase", + "name": Identifier { + "kind": "identifier", + "name": "Bar", + }, + "value": null, + }, + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "Baz", + }, + "value": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "Bar", + }, + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "implements": null, + "kind": "enum", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + "valueType": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test enums can have functions 1`] = ` +Program { + "children": [ + Enum { + "attrGroups": [], + "body": [ + EnumCase { + "kind": "enumcase", + "name": Identifier { + "kind": "identifier", + "name": "MyCase", + }, + "value": Number { + "kind": "number", + "value": "1", + }, + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "bar", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "void", + "raw": "void", + }, + "visibility": "public", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Echo { + "expressions": [ + PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "value", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "MyCase", + }, + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": true, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "baz", + }, + "nullable": false, + "type": null, + "visibility": "protected", + }, + ], + "implements": null, + "kind": "enum", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + "valueType": Name { + "kind": "name", + "name": "int", + "resolution": "uqn", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test enums can implement interfaces 1`] = ` +Program { + "children": [ + Enum { + "attrGroups": [], + "body": [], + "implements": [ + Name { + "kind": "name", + "name": "Bar", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "Baz", + "resolution": "uqn", + }, + ], + "kind": "enum", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + "valueType": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test enums can use traits 1`] = ` +Program { + "children": [ + Enum { + "attrGroups": [], + "body": [ + TraitUse { + "adaptations": [ + TraitPrecedence { + "instead": [ + Name { + "kind": "name", + "name": "Bar", + "resolution": "uqn", + }, + ], + "kind": "traitprecedence", + "method": Identifier { + "kind": "identifier", + "name": "hello", + }, + "trait": Name { + "kind": "name", + "name": "Baz", + "resolution": "uqn", + }, + }, + TraitAlias { + "as": Identifier { + "kind": "identifier", + "name": "earth", + }, + "kind": "traitalias", + "method": Identifier { + "kind": "identifier", + "name": "world", + }, + "trait": Name { + "kind": "name", + "name": "Baz", + "resolution": "uqn", + }, + "visibility": "", + }, + ], + "kind": "traituse", + "traits": [ + Name { + "kind": "name", + "name": "Bar", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "Baz", + "resolution": "uqn", + }, + ], + }, + TraitUse { + "adaptations": null, + "kind": "traituse", + "traits": [ + Name { + "kind": "name", + "name": "Bax", + "resolution": "uqn", + }, + ], + }, + ], + "implements": null, + "kind": "enum", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + "valueType": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test enums can't be parsed with PHP < 8 1`] = `"Parse Error : syntax error, unexpected 'Foo' (T_STRING), expecting ';' on line 1"`; + +exports[`Test enums cannot have properties 1`] = `"Parse Error : syntax error, unexpected 'int' (T_STRING) on line 3"`; + +exports[`Test enums doesn't confuse enums with identifiers 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "enum", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Enum", + }, + }, + Interface { + "attrGroups": [], + "body": [], + "extends": null, + "kind": "interface", + "name": Identifier { + "kind": "identifier", + "name": "Enum", + }, + }, + Trait { + "body": [], + "kind": "trait", + "name": Identifier { + "kind": "identifier", + "name": "Enum", + }, + }, + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "enum", + }, + "nullable": false, + "type": null, + }, + Class { + "attrGroups": [], + "body": [], + "extends": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Enum", + }, + }, + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + ], + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Enum", + }, + }, + Class { + "attrGroups": [], + "body": [], + "extends": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Enum", + }, + }, + Enum { + "attrGroups": [], + "body": [], + "implements": null, + "kind": "enum", + "name": Identifier { + "kind": "identifier", + "name": "extendsFoo", + }, + "valueType": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test enums empty 1`] = ` +Program { + "children": [ + Enum { + "attrGroups": [], + "body": [], + "implements": null, + "kind": "enum", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + "valueType": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test enums may have a backing type 1`] = ` +Program { + "children": [ + Enum { + "attrGroups": [], + "body": [ + EnumCase { + "kind": "enumcase", + "name": Identifier { + "kind": "identifier", + "name": "Hearts", + }, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'H'", + "unicode": false, + "value": "H", + }, + }, + EnumCase { + "kind": "enumcase", + "name": Identifier { + "kind": "identifier", + "name": "Diamonds", + }, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'D'", + "unicode": false, + "value": "D", + }, + }, + EnumCase { + "kind": "enumcase", + "name": Identifier { + "kind": "identifier", + "name": "Clubs", + }, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'C'", + "unicode": false, + "value": "C", + }, + }, + EnumCase { + "kind": "enumcase", + "name": Identifier { + "kind": "identifier", + "name": "Spades", + }, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'S'", + "unicode": false, + "value": "S", + }, + }, + ], + "implements": null, + "kind": "enum", + "name": Identifier { + "kind": "identifier", + "name": "Suit", + }, + "valueType": Name { + "kind": "name", + "name": "string", + "resolution": "uqn", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test enums non-empty 1`] = ` +Program { + "children": [ + Enum { + "attrGroups": [], + "body": [ + EnumCase { + "kind": "enumcase", + "name": Identifier { + "kind": "identifier", + "name": "Hearts", + }, + "value": null, + }, + EnumCase { + "kind": "enumcase", + "name": Identifier { + "kind": "identifier", + "name": "Diamonds", + }, + "value": null, + }, + EnumCase { + "kind": "enumcase", + "name": Identifier { + "kind": "identifier", + "name": "Clubs", + }, + "value": null, + }, + EnumCase { + "kind": "enumcase", + "name": Identifier { + "kind": "identifier", + "name": "Spades", + }, + "value": null, + }, + ], + "implements": null, + "kind": "enum", + "name": Identifier { + "kind": "identifier", + "name": "Suit", + }, + "valueType": null, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/eval.test.js.snap b/test/snapshot/__snapshots__/eval.test.js.snap new file mode 100644 index 000000000..af42e6f78 --- /dev/null +++ b/test/snapshot/__snapshots__/eval.test.js.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`eval simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Eval { + "kind": "eval", + "source": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""command"", + "unicode": false, + "value": "command", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/exit.test.js.snap b/test/snapshot/__snapshots__/exit.test.js.snap new file mode 100644 index 000000000..5b6e258b1 --- /dev/null +++ b/test/snapshot/__snapshots__/exit.test.js.snap @@ -0,0 +1,182 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`exit argument 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "exit", + "useDie": false, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`exit die 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": null, + "kind": "exit", + "useDie": true, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`exit die with empty expression 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": null, + "kind": "exit", + "useDie": true, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`exit die with expression 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "10", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "type": "+", + }, + "kind": "exit", + "useDie": true, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`exit die without expression 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": null, + "kind": "exit", + "useDie": true, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`exit exit with empty expression 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": null, + "kind": "exit", + "useDie": false, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`exit exit with expression 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "10", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "type": "+", + }, + "kind": "exit", + "useDie": false, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`exit exit without expression 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": null, + "kind": "exit", + "useDie": false, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`exit simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": null, + "kind": "exit", + "useDie": false, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/expr.test.js.snap b/test/snapshot/__snapshots__/expr.test.js.snap new file mode 100644 index 000000000..ba219eb0d --- /dev/null +++ b/test/snapshot/__snapshots__/expr.test.js.snap @@ -0,0 +1,2374 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test expressions chaining calls (derefenceable) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "10", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "b", + }, + "parenthesizedExpression": true, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions chaining calls (derefenceable) 2`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "0", + }, + "what": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "3", + }, + }, + ], + "kind": "array", + "shortForm": false, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions chaining calls (derefenceable) 3`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "baz", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + ], + "kind": "call", + "what": Post { + "kind": "post", + "parenthesizedExpression": true, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions chaining calls (derefenceable) 4`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Post { + "kind": "post", + "parenthesizedExpression": true, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "baz", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'bar' (T_STRING), expecting ';' on line 1", + "token": "'bar' (T_STRING)", + }, + Error { + "expected": undefined, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '::' (T_DOUBLE_COLON) on line 1", + "token": "'::' (T_DOUBLE_COLON)", + }, + ], + "kind": "program", +} +`; + +exports[`Test expressions chaining calls (derefenceable) 5`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "baz", + }, + "what": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions fix #234 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "0", + }, + "what": New { + "arguments": [], + "kind": "new", + "parenthesizedExpression": true, + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions fix #235 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "self", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "sElF", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "parent", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "pArEnT", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": StaticReference { + "kind": "staticreference", + "raw": "static", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions should assign class static 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "what": Name { + "kind": "name", + "name": "a", + "resolution": "uqn", + }, + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions should fail to assign class constants 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "b", + }, + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "VARIABLE", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '=' on line 1", + "token": "'='", + }, + ], + "kind": "program", +} +`; + +exports[`Test expressions should fail to assign constants 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Name { + "kind": "name", + "name": "a", + "resolution": "uqn", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test assignements 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": ".=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "+=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "-=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "*=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "**=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "/=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "&=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "|=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "%=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "^=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "<<=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": ">>=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test binary 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "|", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "&", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "^", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""1"", + "unicode": false, + "value": "1", + }, + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""3"", + "unicode": false, + "value": "3", + }, + "type": ".", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "+", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "-", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "*", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "/", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "%", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "**", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "<<", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": ">>", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test cast 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(int)", + "type": "int", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(integer)", + "type": "int", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(bool)", + "type": "bool", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(boolean)", + "type": "bool", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(float)", + "type": "float", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(double)", + "type": "float", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(real)", + "type": "float", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(string)", + "type": "string", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(binary)", + "type": "binary", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(array)", + "type": "array", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(object)", + "type": "object", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "cast", + "raw": "(unset)", + "type": "unset", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test cast extension - #171 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Variable { + "cast": "int", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(int)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "int", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(integer)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "bool", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(bool)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "bool", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(boolean)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "float", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(float)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "float", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(double)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "float", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(real)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "string", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(string)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "binary", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(binary)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "array", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(array)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "object", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(object)", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "cast": "unset", + "curly": false, + "kind": "variable", + "name": "var", + "rawCast": "(unset)", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test exit 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Exit { + "expression": Number { + "kind": "number", + "value": "1", + }, + "kind": "exit", + "useDie": false, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Exit { + "expression": null, + "kind": "exit", + "useDie": true, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Exit { + "expression": null, + "kind": "exit", + "useDie": false, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test fail new 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": New { + "arguments": [], + "kind": "new", + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Identifier { + "kind": "identifier", + "name": "0", + }, + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": [ + 105, + 109, + "-", + 222, + ], + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected '0' (T_LNUMBER) on line 2", + "token": "'0' (T_LNUMBER)", + }, + ], + "kind": "program", +} +`; + +exports[`Test expressions test generators 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Yield { + "key": null, + "kind": "yield", + "value": Number { + "kind": "number", + "value": "0", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": YieldFrom { + "kind": "yieldfrom", + "value": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Yield { + "key": Number { + "kind": "number", + "value": "1", + }, + "kind": "yield", + "value": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "gen", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test if based returns 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + "type": "??", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": RetIf { + "falseExpr": Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + "kind": "retif", + "test": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Number { + "kind": "number", + "value": "5", + }, + "type": ">", + }, + "trueExpr": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": RetIf { + "falseExpr": Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + "kind": "retif", + "test": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "trueExpr": null, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test incr/decr 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Post { + "kind": "post", + "loc": Location { + "end": Position { + "column": 11, + "line": 2, + "offset": 12, + }, + "source": null, + "start": Position { + "column": 6, + "line": 2, + "offset": 7, + }, + }, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 8, + "line": 2, + "offset": 9, + }, + "source": null, + "start": Position { + "column": 6, + "line": 2, + "offset": 7, + }, + }, + "name": "i", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 11, + "line": 2, + "offset": 12, + }, + "source": null, + "start": Position { + "column": 6, + "line": 2, + "offset": 7, + }, + }, + }, + ExpressionStatement { + "expression": Post { + "kind": "post", + "loc": Location { + "end": Position { + "column": 11, + "line": 3, + "offset": 24, + }, + "source": null, + "start": Position { + "column": 6, + "line": 3, + "offset": 19, + }, + }, + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 8, + "line": 3, + "offset": 21, + }, + "source": null, + "start": Position { + "column": 6, + "line": 3, + "offset": 19, + }, + }, + "name": "i", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 11, + "line": 3, + "offset": 24, + }, + "source": null, + "start": Position { + "column": 6, + "line": 3, + "offset": 19, + }, + }, + }, + ExpressionStatement { + "expression": Pre { + "kind": "pre", + "loc": Location { + "end": Position { + "column": 11, + "line": 4, + "offset": 36, + }, + "source": null, + "start": Position { + "column": 6, + "line": 4, + "offset": 31, + }, + }, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 4, + "offset": 35, + }, + "source": null, + "start": Position { + "column": 8, + "line": 4, + "offset": 33, + }, + }, + "name": "i", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 11, + "line": 4, + "offset": 36, + }, + "source": null, + "start": Position { + "column": 6, + "line": 4, + "offset": 31, + }, + }, + }, + ExpressionStatement { + "expression": Pre { + "kind": "pre", + "loc": Location { + "end": Position { + "column": 11, + "line": 5, + "offset": 48, + }, + "source": null, + "start": Position { + "column": 6, + "line": 5, + "offset": 43, + }, + }, + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 5, + "offset": 47, + }, + "source": null, + "start": Position { + "column": 8, + "line": 5, + "offset": 45, + }, + }, + "name": "i", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 11, + "line": 5, + "offset": 48, + }, + "source": null, + "start": Position { + "column": 6, + "line": 5, + "offset": 43, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 4, + "line": 6, + "offset": 53, + }, + "source": null, + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test expressions test more binary ops (formerly bool) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "&&", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "and", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "||", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "or", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "xor", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "===", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "!==", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "==", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "!=", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": ">", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "<", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": ">=", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "<=", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "<=>", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "type": "instanceof", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test nested expressions precedence 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "5", + }, + "right": Number { + "kind": "number", + "value": "2", + }, + "type": "*", + }, + "right": Number { + "kind": "number", + "value": "1", + }, + "type": "+", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "5", + }, + "right": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "2", + }, + "parenthesizedExpression": true, + "right": Number { + "kind": "number", + "value": "1", + }, + "type": "+", + }, + "type": "*", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "c", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "2", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "/", + }, + "type": "+", + }, + "right": Number { + "kind": "number", + "value": "4", + }, + "type": "+", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "d", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "2", + }, + "type": "!==", + }, + "right": Number { + "kind": "number", + "value": "3", + }, + "type": "&&", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test new 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "\\foo", + "resolution": "fqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": New { + "arguments": [], + "kind": "new", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "class", + }, + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "rn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": New { + "arguments": [], + "kind": "new", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": New { + "arguments": [], + "kind": "new", + "what": Class { + "attrGroups": [], + "body": [], + "extends": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + "implements": [ + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + ], + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": null, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test node references 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": StaticReference { + "kind": "staticreference", + "raw": "static", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test silent 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Silent { + "expr": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "trigger_error", + "resolution": "uqn", + }, + }, + "kind": "silent", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test expressions test unary 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "~", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "!", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/foreach.test.js.snap b/test/snapshot/__snapshots__/foreach.test.js.snap new file mode 100644 index 000000000..d75a9c7ce --- /dev/null +++ b/test/snapshot/__snapshots__/foreach.test.js.snap @@ -0,0 +1,722 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`foreach as list 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + "value": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + ], + "kind": "list", + "shortForm": false, + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`foreach as list with key 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "v", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "key": Variable { + "curly": false, + "kind": "variable", + "name": "v", + }, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + "value": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + ], + "kind": "list", + "shortForm": false, + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`foreach as short list 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + "value": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + ], + "kind": "list", + "shortForm": true, + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`foreach as short list with key 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "v", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "key": Variable { + "curly": false, + "kind": "variable", + "name": "v", + }, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + "value": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + ], + "kind": "list", + "shortForm": true, + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`foreach as variable 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`foreach as variable by ref 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + "value": Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`foreach unpacking #2 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "print_r", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": true, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "3", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "4", + }, + }, + ], + "kind": "array", + "shortForm": false, + }, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`foreach unpacking #3 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "print_r", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": true, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "3", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "4", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`foreach unpacking #4 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "print_r", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": true, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + ], + "kind": "array", + "shortForm": false, + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "3", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "4", + }, + }, + ], + "kind": "array", + "shortForm": false, + }, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`foreach unpacking 1`] = ` +Program { + "children": [ + Foreach { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "print_r", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": true, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "3", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "4", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/function.test.js.snap b/test/snapshot/__snapshots__/function.test.js.snap new file mode 100644 index 000000000..2879e51d4 --- /dev/null +++ b/test/snapshot/__snapshots__/function.test.js.snap @@ -0,0 +1,1786 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Function tests Test readonly function properties are only for class constructor 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 1, + "kind": "parameter", + "name": null, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": null, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "fun", + }, + "nullable": false, + "type": null, + }, + ExpressionStatement { + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "id", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + Block { + "children": [], + "kind": "block", + }, + ], + "errors": [ + Error { + "expected": undefined, + "kind": "error", + "line": 2, + "message": "readonly properties can be used only on class constructor on line 2", + "token": undefined, + }, + Error { + "expected": 222, + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected 'readonly' (T_READ_ONLY), expecting T_VARIABLE on line 2", + "token": "'readonly' (T_READ_ONLY)", + }, + Error { + "expected": [ + ",", + ")", + ], + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected 'readonly' (T_READ_ONLY) on line 2", + "token": "'readonly' (T_READ_ONLY)", + }, + Error { + "expected": ")", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected 'readonly' (T_READ_ONLY), expecting ')' on line 2", + "token": "'readonly' (T_READ_ONLY)", + }, + Error { + "expected": "{", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected 'readonly' (T_READ_ONLY), expecting '{' on line 2", + "token": "'readonly' (T_READ_ONLY)", + }, + Error { + "expected": 187, + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected 'int' (T_STRING), expecting T_CLASS on line 2", + "token": "'int' (T_STRING)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected ')', expecting ';' on line 2", + "token": "')'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected ')' on line 2", + "token": "')'", + }, + Error { + "expected": ";", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected '{', expecting ';' on line 2", + "token": "'{'", + }, + ], + "kind": "program", +} +`; + +exports[`Function tests array pass by reference are not confused with intersection 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": true, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "params", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests first class callable support 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "callable", + }, + "operator": "=", + "right": Call { + "arguments": [ + VariadicPlaceholder { + "kind": "variadicplaceholder", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "strlen", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "callable", + }, + "operator": "=", + "right": Call { + "arguments": [ + VariadicPlaceholder { + "kind": "variadicplaceholder", + }, + ], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "doSomething", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "item", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "callable", + }, + "operator": "=", + "right": Call { + "arguments": [ + VariadicPlaceholder { + "kind": "variadicplaceholder", + }, + ], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "doSomething", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "item", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "callable", + }, + "operator": "=", + "right": Call { + "arguments": [ + VariadicPlaceholder { + "kind": "variadicplaceholder", + }, + ], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "doSomething", + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests first class callable support requires PHP 8.1+ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "callable", + }, + "operator": "=", + "right": Call { + "arguments": [ + variadic { + "kind": "variadic", + "what": undefined, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "strlen", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected ')' on line 2", + "token": "')'", + }, + Error { + "expected": ")", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected ';', expecting ')' on line 2", + "token": "';'", + }, + ], + "kind": "program", +} +`; + +exports[`Function tests implement #113 : typehint nodes 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": Number { + "kind": "number", + "value": "1", + }, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + "value": Number { + "kind": "number", + "value": "1", + }, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "c", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "bool", + "raw": "bool", + }, + "value": Number { + "kind": "number", + "value": "1", + }, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "d", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "e", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "callable", + }, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "f", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "int\\bar", + "resolution": "qn", + }, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": true, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "params", + }, + "nullable": true, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + "value": null, + "variadic": true, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": true, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": true, + "type": TypeReference { + "kind": "typereference", + "name": "object", + "raw": "object", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests implement #196 : set function name as identifier 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 18, + "value": "/* f */", + }, + ], + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "f", + }, + "nullable": false, + "type": null, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "offset": 18, + "value": "/* f */", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests spread array pass by reference are not intersection 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": true, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "params", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": true, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test arrow function php 7.4 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test danging comma in closure use-block php 8.0 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "curly": false, + "kind": "variable", + "name": "one", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test danging comma in closure use-block with multiple php 8.0 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "curly": false, + "kind": "variable", + "name": "one", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "two", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test danging comma in closure use-block with multiple/refs php 8.0 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "one", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "two", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "curly": false, + "kind": "variable", + "name": "three", + }, + Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "four", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test danging comma in closure use-block with refs php 8.0 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "one", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test danging comma in function php 8.0 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "c", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test double danging comma in closure use-block php 8.0 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "curly": false, + "kind": "variable", + "name": "one", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": 222, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected ',', expecting T_VARIABLE on line 1", + "token": "','", + }, + ], + "kind": "program", +} +`; + +exports[`Function tests test function intersection types 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "readonly": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + ], + }, + "value": Number { + "kind": "number", + "value": "1", + }, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "readonly": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "Bar", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + ], + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test function parsing 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Number { + "kind": "number", + "value": "1", + }, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "callable", + }, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": true, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "params", + }, + "nullable": true, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + "value": null, + "variadic": true, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": true, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": true, + "type": Name { + "kind": "name", + "name": "boolean", + "resolution": "uqn", + }, + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + "kind": "return", + }, + ], + "kind": "block", + }, + "byref": true, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + "uses": [ + Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "c", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "d", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "operator": "=", + "right": Call { + "arguments": [ + variadic { + "kind": "variadic", + "what": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": NullKeyword { + "kind": "nullkeyword", + "raw": "null", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "3", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test function union types 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "readonly": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + ], + }, + "value": Number { + "kind": "number", + "value": "1", + }, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "readonly": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "Bar", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + ], + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test reserved word for function name error 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [ + Error { + "expected": 105, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'list' (T_LIST), expecting T_STRING on line 1", + "token": "'list' (T_LIST)", + }, + ], + "kind": "program", +} +`; + +exports[`Function tests test short function intersection types 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "readonly": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + ], + }, + "value": Number { + "kind": "number", + "value": "1", + }, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "readonly": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "Bar", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": String { + "isDoubleQuote": true, + "kind": "string", + "raw": """", + "unicode": false, + "value": "", + }, + "byref": false, + "isStatic": false, + "kind": "arrowfunc", + "nullable": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test short function union types 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Closure { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "readonly": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + ], + }, + "value": Number { + "kind": "number", + "value": "1", + }, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "readonly": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "Bar", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": String { + "isDoubleQuote": true, + "kind": "string", + "raw": """", + "unicode": false, + "value": "", + }, + "byref": false, + "isStatic": false, + "kind": "arrowfunc", + "nullable": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test static closure 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": true, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test variadic call error 1`] = `"Unexpected non-variadic argument after a variadic argument on line 1"`; + +exports[`Function tests test variadic function error 1 1`] = `"Unexpected parameter after a variadic parameter on line 1"`; + +exports[`Function tests test variadic function error 2 1`] = `"Unexpected parameter after a variadic parameter on line 1"`; + +exports[`Function tests test without danging comma in closure use-block php 8.0 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "curly": false, + "kind": "variable", + "name": "one", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Function tests test without danging comma in closure use-block with refs php 8.0 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [ + Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "one", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/global.test.js.snap b/test/snapshot/__snapshots__/global.test.js.snap new file mode 100644 index 000000000..eeeb6d5e2 --- /dev/null +++ b/test/snapshot/__snapshots__/global.test.js.snap @@ -0,0 +1,44 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`global mutliple 1`] = ` +Program { + "children": [ + Global { + "items": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + ], + "kind": "global", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`global simple 1`] = ` +Program { + "children": [ + Global { + "items": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + "kind": "global", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/goto.test.js.snap b/test/snapshot/__snapshots__/goto.test.js.snap new file mode 100644 index 000000000..bb89ebc35 --- /dev/null +++ b/test/snapshot/__snapshots__/goto.test.js.snap @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`goto simple 1`] = ` +Program { + "children": [ + Goto { + "kind": "goto", + "label": Identifier { + "kind": "identifier", + "name": "a", + }, + }, + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Foo"", + "unicode": false, + "value": "Foo", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`goto simple 2`] = ` +Program { + "children": [ + Goto { + "kind": "goto", + "label": Identifier { + "kind": "identifier", + "name": "longName", + }, + }, + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""Foo"", + "unicode": false, + "value": "Foo", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/graceful.test.js.snap b/test/snapshot/__snapshots__/graceful.test.js.snap new file mode 100644 index 000000000..d1bf9b28c --- /dev/null +++ b/test/snapshot/__snapshots__/graceful.test.js.snap @@ -0,0 +1,919 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test graceful mode to suppress errors interface 1`] = ` +Program { + "children": [ + Interface { + "attrGroups": [], + "body": [], + "extends": null, + "kind": "interface", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "errors": [ + Error { + "expected": "{", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'implement' (T_STRING), expecting '{' on line 1", + "token": "'implement' (T_STRING)", + }, + Error { + "expected": [ + 198, + 182, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'baz' (T_STRING) on line 1", + "token": "'baz' (T_STRING)", + }, + Error { + "expected": [ + 198, + 182, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '{' on line 1", + "token": "'{'", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors should contain 2 errors 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Closure { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "operator": "=", + "right": undefined, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "byref": false, + "isStatic": false, + "kind": "closure", + "nullable": false, + "type": null, + "uses": [], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, unexpected '}' on line 4", + "token": "'}'", + }, + Error { + "expected": ";", + "kind": "error", + "line": 5, + "message": "Parse Error : syntax error, unexpected '}', expecting ';' on line 5", + "token": "'}'", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors should fail ! 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Literal { + "kind": "literal", + "value": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors should fail with '[' and '}' 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "]", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '}', expecting ']' on line 1", + "token": "'}'", + }, + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '}', expecting ';' on line 1", + "token": "'}'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '}' on line 1", + "token": "'}'", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors should fail with '{' and ']' 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "}", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected ']', expecting '}' on line 1", + "token": "']'", + }, + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected ']', expecting ';' on line 1", + "token": "']'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected ']' on line 1", + "token": "']'", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors staticlookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Literal { + "kind": "literal", + "value": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + }, + "what": Name { + "kind": "name", + "name": "Order", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "(", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected ';', expecting '(' on line 1", + "token": "';'", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors test class 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "onst", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + "value": null, + }, + ], + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "errors": [ + Error { + "expected": 222, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'const' (T_CONST), expecting T_VARIABLE on line 1", + "token": "'const' (T_CONST)", + }, + Error { + "expected": [ + ",", + ";", + "=", + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'A' (T_STRING) on line 1", + "token": "'A' (T_STRING)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'A' (T_STRING), expecting ';' on line 1", + "token": "'A' (T_STRING)", + }, + Error { + "expected": [ + 198, + 222, + 182, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '=' on line 1", + "token": "'='", + }, + Error { + "expected": [ + 198, + 222, + 182, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '1' (T_LNUMBER) on line 1", + "token": "'1' (T_LNUMBER)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '}' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors test expr 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "right": undefined, + "type": "-", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected ';' on line 1", + "token": "';'", + }, + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '$foo' (T_VARIABLE), expecting ';' on line 1", + "token": "'$foo' (T_VARIABLE)", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors test flags (2) 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": null, + "byref": false, + "isAbstract": true, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "func", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "errors": [ + Error { + "expected": 187, + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected 'final' (T_FINAL), expecting T_CLASS on line 2", + "token": "'final' (T_FINAL)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, expecting ';' on line 4", + "token": "the end of file (EOF)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, expecting '}' on line 4", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors test flags (3) 1`] = ` +Program { + "children": [ + Trait { + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": null, + "byref": false, + "isAbstract": true, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "func", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "kind": "trait", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "errors": [ + Error { + "expected": 187, + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected 'final' (T_FINAL), expecting T_CLASS on line 2", + "token": "'final' (T_FINAL)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, expecting ';' on line 4", + "token": "the end of file (EOF)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, expecting '}' on line 4", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors test flags 1`] = ` +Program { + "children": [ + Interface { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": null, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": "func", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "kind": "interface", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "errors": [ + Error { + "expected": 187, + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected 'final' (T_FINAL), expecting T_CLASS on line 2", + "token": "'final' (T_FINAL)", + }, + Error { + "expected": undefined, + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected 'abstract' (T_ABSTRACT) on line 3", + "token": "'abstract' (T_ABSTRACT)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, expecting ';' on line 4", + "token": "the end of file (EOF)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error, expecting '}' on line 4", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors test function arguments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "arg", + }, + ], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "operator": "=", + "right": New { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "baz", + }, + Noop { + "kind": "noop", + }, + ], + "kind": "new", + "what": Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ")", + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected ',', expecting ')' on line 3", + "token": "','", + }, + Error { + "expected": ";", + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected ',', expecting ';' on line 3", + "token": "','", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected ',' on line 3", + "token": "','", + }, + Error { + "expected": ";", + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected '$foo' (T_VARIABLE), expecting ';' on line 3", + "token": "'$foo' (T_VARIABLE)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected ')', expecting ';' on line 3", + "token": "')'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected ')' on line 3", + "token": "')'", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors test method chains 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "", + }, + "what": Call { + "arguments": [ + Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "once", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + }, + ], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "expects", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "controller", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": [ + 105, + 222, + "$", + "{", + ], + "kind": "error", + "line": 4, + "message": "Parse Error : syntax error on line 4", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test graceful mode to suppress errors trait 1`] = ` +Program { + "children": [ + Trait { + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "mplement", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + "value": null, + }, + ], + "visibility": "", + }, + ], + "kind": "trait", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "errors": [ + Error { + "expected": "{", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'extends' (T_EXTENDS), expecting '{' on line 1", + "token": "'extends' (T_EXTENDS)", + }, + Error { + "expected": 222, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'implement' (T_STRING), expecting T_VARIABLE on line 1", + "token": "'implement' (T_STRING)", + }, + Error { + "expected": [ + ",", + ";", + "=", + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'baz' (T_STRING) on line 1", + "token": "'baz' (T_STRING)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'baz' (T_STRING), expecting ';' on line 1", + "token": "'baz' (T_STRING)", + }, + Error { + "expected": [ + 198, + 222, + 182, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '{' on line 1", + "token": "'{'", + }, + ], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/heredoc.test.js.snap b/test/snapshot/__snapshots__/heredoc.test.js.snap new file mode 100644 index 000000000..cdf9be706 --- /dev/null +++ b/test/snapshot/__snapshots__/heredoc.test.js.snap @@ -0,0 +1,2227 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`heredoc Can't parse multiple flexible nowdoc blocks with different indentation #508 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Nowdoc { + "kind": "nowdoc", + "label": "EOT", + "raw": "<<<'EOT' + a + + EOT", + "value": "a +", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "operator": "=", + "right": Nowdoc { + "kind": "nowdoc", + "label": "EOT", + "raw": "<<<'EOT' + b + EOT", + "value": "b", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`heredoc Flexible heredoc syntax: 4 spaces of indentation 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "label": "END", + "raw": "<<bar[1]} + b + c + END", + "type": "heredoc", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " a + ", + "unicode": false, + "value": " a + ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " + b + c + ", + "unicode": false, + "value": " + b +c", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`heredoc empty 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "label": "TEST", + "raw": "<<foo. +Now, I am printing some {$foo->bar[1]}. +This should print a capital 'A': A +EOT", + "type": "heredoc", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "My name is "", + "unicode": false, + "value": "My name is "", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "name", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "". I am printing some ", + "unicode": false, + "value": "". I am printing some ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": ". +Now, I am printing some ", + "unicode": false, + "value": ". +Now, I am printing some ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": ". +This should print a capital 'A': A +", + "unicode": false, + "value": ". +This should print a capital 'A': A", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/if.test.js.snap b/test/snapshot/__snapshots__/if.test.js.snap new file mode 100644 index 000000000..79fac2e5e --- /dev/null +++ b/test/snapshot/__snapshots__/if.test.js.snap @@ -0,0 +1,598 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test IF statements test common cases 1`] = ` +Program { + "children": [ + If { + "alternate": If { + "alternate": If { + "alternate": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""else"", + "unicode": false, + "value": "else", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""2nd"", + "unicode": false, + "value": "2nd", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "kind": "if", + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + }, + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""false"", + "unicode": false, + "value": "false", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "kind": "if", + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + }, + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""is true"", + "unicode": false, + "value": "is true", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "kind": "if", + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test IF statements test issue #84 1`] = ` +Program { + "children": [ + Inline { + "kind": "inline", + "raw": " + ", + "value": " + ", + }, + If { + "alternate": Block { + "children": [ + Inline { + "kind": "inline", + "raw": " + ", + "value": " ", + }, + ], + "kind": "block", + }, + "body": Block { + "children": [ + Inline { + "kind": "inline", + "raw": " + ", + "value": " ", + }, + ], + "kind": "block", + }, + "kind": "if", + "shortForm": true, + "test": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + Inline { + "kind": "inline", + "raw": " + ", + "value": " ", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test IF statements test issue #168 1`] = ` +Program { + "children": [ + If { + "alternate": null, + "body": null, + "kind": "if", + "loc": Location { + "end": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + "source": "if ($foo);", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "shortForm": false, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "$foo", + "start": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + }, + "name": "foo", + }, + }, + Inline { + "kind": "inline", + "loc": Location { + "end": Position { + "column": 6, + "line": 2, + "offset": 26, + }, + "source": " ", + "start": Position { + "column": 0, + "line": 2, + "offset": 20, + }, + }, + "raw": " + ", + "value": " ", + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 6, + "line": 2, + "offset": 26, + }, + "source": " + ", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test IF statements test issue #168 2`] = ` +Program { + "children": [ + If { + "alternate": null, + "body": null, + "kind": "if", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "if ($foo)", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "shortForm": false, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "$foo", + "start": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + }, + "name": "foo", + }, + }, + Inline { + "kind": "inline", + "loc": Location { + "end": Position { + "column": 6, + "line": 2, + "offset": 25, + }, + "source": " ", + "start": Position { + "column": 0, + "line": 2, + "offset": 19, + }, + }, + "raw": " + ", + "value": " ", + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 6, + "line": 2, + "offset": 25, + }, + "source": " + ", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test IF statements test issue #168 3`] = ` +Program { + "children": [ + If { + "alternate": null, + "body": null, + "kind": "if", + "loc": Location { + "end": Position { + "column": 7, + "line": 2, + "offset": 23, + }, + "source": "if ($foo) + ;", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "shortForm": false, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "$foo", + "start": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + }, + "name": "foo", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 7, + "line": 2, + "offset": 23, + }, + "source": "", + "value": "", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test lexer initial state parse asp echo tag 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + ], + "kind": "echo", + "shortForm": true, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test lexer initial state parse asp tag 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test lexer initial state parse short echo 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + ], + "kind": "echo", + "shortForm": true, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test lexer initial state parse short tag 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test lexer test #148 - sensitive lexer 1`] = ` +[ + [ + "T_OPEN_TAG", + "", + 1, + ], + [ + "T_WHITESPACE", + " ", + 1, + ], + [ + "T_STRING", + "list", + 1, + ], + ";", +] +`; + +exports[`Test lexer test #1003 - null-safe operator with reserved keyword 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "class", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test lexer test comments 1`] = ` +Program { + "children": [ + Inline { + "kind": "inline", + "raw": " + ", + "value": " + ", + }, + Inline { + "kind": "inline", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 20, + "value": "// simple comment ", + }, + ], + "raw": " + ", + "value": " ", + }, + Inline { + "kind": "inline", + "leadingComments": [ + CommentLine { + "kind": "commentline", + "offset": 57, + "value": "// another line ", + }, + ], + "raw": " + ", + "value": " ", + }, + Inline { + "kind": "inline", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "offset": 92, + "value": "/**/", + }, + ], + "raw": " + ", + "trailingComments": [ + CommentLine { + "kind": "commentline", + "offset": 112, + "value": "// last comment +", + }, + ], + "value": " ", + }, + ], + "comments": [ + CommentLine { + "kind": "commentline", + "offset": 20, + "value": "// simple comment ", + }, + CommentLine { + "kind": "commentline", + "offset": 57, + "value": "// another line ", + }, + CommentBlock { + "kind": "commentblock", + "offset": 92, + "value": "/**/", + }, + CommentLine { + "kind": "commentline", + "offset": 112, + "value": "// last comment +", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test lexer test tokens 1`] = ` +[ + [ + "T_OPEN_TAG", + " 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "$a", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "a", + }, + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "$a = $b + 1", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$b", + "start": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + }, + "name": "b", + }, + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "$b + 1", + "start": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + }, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "1", + "start": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + }, + "value": "1", + }, + "type": "+", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "$a = $b + 1", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test #164 : expr must include ; 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 2, + "line": 1, + "offset": 2, + }, + "source": "$a", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "a", + }, + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$a = $b + 1;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "$b", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "name": "b", + }, + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$b + 1", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "1", + "start": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + }, + "value": "1", + }, + "type": "+", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$a = $b + 1;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$a = $b + 1;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test #202 : include calling argument 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$arg", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + "name": "arg", + }, + ], + "kind": "call", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "$foo->bar->baz($arg);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "$foo->bar->baz", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "baz", + "start": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + }, + "name": "baz", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "$foo->bar", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "bar", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "bar", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$foo", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "foo", + }, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "$foo->bar->baz($arg);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "$foo->bar->baz($arg);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test #230 : check location 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "$var1", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var1", + }, + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var1 + $var2", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var2", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "var2", + }, + "type": "+", + }, + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "$var1 + $var2 + $var3;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "$var3", + "start": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + }, + "name": "var3", + }, + "type": "+", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "$var1 + $var2 + $var3;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "$var1 + $var2 + $var3;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test #230 : check location on cast 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Cast { + "expr": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var1", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "var1", + }, + "kind": "cast", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "(string)$var1", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "raw": "(string)", + "type": "string", + }, + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "(string)$var1 + $var2;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "$var2", + "start": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + }, + "name": "var2", + }, + "type": "+", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "(string)$var1 + $var2;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "(string)$var1 + $var2;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test #230 : check location on retif 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": RetIf { + "falseExpr": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 57, + "line": 1, + "offset": 57, + }, + "source": "$innerFalse", + "start": Position { + "column": 45, + "line": 1, + "offset": 45, + }, + }, + "name": "innerFalse", + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 57, + "line": 1, + "offset": 57, + }, + "source": "$var1 + $var2 ? true : $false ? $innerTrue : $innerFalse;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "test": RetIf { + "falseExpr": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "$false", + "start": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + }, + "name": "false", + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "$var1 + $var2 ? true : $false", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "test": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "$var1", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var1", + }, + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var1 + $var2", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var2", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "var2", + }, + "type": "+", + }, + "trueExpr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "true", + "start": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + }, + "raw": "true", + "value": true, + }, + }, + "trueExpr": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 42, + "line": 1, + "offset": 42, + }, + "source": "$innerTrue", + "start": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + }, + "name": "innerTrue", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 57, + "line": 1, + "offset": 57, + }, + "source": "$var1 + $var2 ? true : $false ? $innerTrue : $innerFalse;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 57, + "line": 1, + "offset": 57, + }, + "source": "$var1 + $var2 ? true : $false ? $innerTrue : $innerFalse;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test abstract class (inner statement) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": true, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 38, + "line": 1, + "offset": 38, + }, + "source": "abstract class Foo {}", + "start": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 35, + "line": 1, + "offset": 35, + }, + "source": "Foo", + "start": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + }, + "name": "Foo", + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 40, + "line": 1, + "offset": 40, + }, + "source": "{ abstract class Foo {} }", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + }, + "byref": false, + "kind": "function", + "loc": Location { + "end": Position { + "column": 40, + "line": 1, + "offset": 40, + }, + "source": "function foo()", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "foo", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 40, + "line": 1, + "offset": 40, + }, + "source": "function foo() { abstract class Foo {} }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test abstract class 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": true, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "abstract class Foo {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "Foo", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "abstract class Foo {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test array 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "1", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "1", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "2", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "2", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "3", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "3", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "value": "3", + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "array(1, 2, 3);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "array(1, 2, 3);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "array(1, 2, 3);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test array nested 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "array(1, 2, 3)", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "unpack": false, + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "1", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "1", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + "source": "2", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + "source": "2", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "3", + "start": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "3", + "start": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + }, + "value": "3", + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "array(1, 2, 3)", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "shortForm": false, + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "array(array(1, 2, 3));", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "array(array(1, 2, 3));", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "array(array(1, 2, 3));", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test array short form 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 2, + "line": 1, + "offset": 2, + }, + "source": "1", + "start": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 2, + "line": 1, + "offset": 2, + }, + "source": "1", + "start": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + }, + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "2", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "2", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "3", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "3", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "value": "3", + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "[1, 2, 3];", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": true, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "[1, 2, 3];", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "[1, 2, 3];", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test array short form nested 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "[1, 2, 3]", + "start": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + }, + "unpack": false, + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 3, + "line": 1, + "offset": 3, + }, + "source": "1", + "start": Position { + "column": 2, + "line": 1, + "offset": 2, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 3, + "line": 1, + "offset": 3, + }, + "source": "1", + "start": Position { + "column": 2, + "line": 1, + "offset": 2, + }, + }, + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "2", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "2", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "value": "2", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "3", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "3", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "value": "3", + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "[1, 2, 3]", + "start": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + }, + "shortForm": true, + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "[[1, 2, 3]];", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": true, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "[[1, 2, 3]];", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "[[1, 2, 3]];", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test array with keys, byRef and unpack 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 60, + "line": 1, + "offset": 60, + }, + "source": "$var = [1, 'foo', 'test' => $foo, 'test' => &$foo, ...$var];", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "1", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "unpack": false, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "1", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + "source": "'foo'", + "start": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + }, + "unpack": false, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + "source": "'foo'", + "start": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + }, + "raw": "'foo'", + "unicode": false, + "value": "foo", + }, + }, + Entry { + "byRef": false, + "key": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 24, + "line": 1, + "offset": 24, + }, + "source": "'test'", + "start": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + }, + "raw": "'test'", + "unicode": false, + "value": "test", + }, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + "source": "'test' => $foo", + "start": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + "source": "$foo", + "start": Position { + "column": 28, + "line": 1, + "offset": 28, + }, + }, + "name": "foo", + }, + }, + Entry { + "byRef": true, + "key": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 40, + "line": 1, + "offset": 40, + }, + "source": "'test'", + "start": Position { + "column": 34, + "line": 1, + "offset": 34, + }, + }, + "raw": "'test'", + "unicode": false, + "value": "test", + }, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 49, + "line": 1, + "offset": 49, + }, + "source": "'test' => &$foo", + "start": Position { + "column": 34, + "line": 1, + "offset": 34, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 49, + "line": 1, + "offset": 49, + }, + "source": "$foo", + "start": Position { + "column": 45, + "line": 1, + "offset": 45, + }, + }, + "name": "foo", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 58, + "line": 1, + "offset": 58, + }, + "source": "...$var", + "start": Position { + "column": 51, + "line": 1, + "offset": 51, + }, + }, + "unpack": true, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 58, + "line": 1, + "offset": 58, + }, + "source": "$var", + "start": Position { + "column": 54, + "line": 1, + "offset": 54, + }, + }, + "name": "var", + }, + }, + ], + "kind": "array", + "loc": Location { + "end": Position { + "column": 59, + "line": 1, + "offset": 59, + }, + "source": "[1, 'foo', 'test' => $foo, 'test' => &$foo, ...$var]", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "shortForm": true, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 60, + "line": 1, + "offset": 60, + }, + "source": "$var = [1, 'foo', 'test' => $foo, 'test' => &$foo, ...$var];", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 60, + "line": 1, + "offset": 60, + }, + "source": "$var = [1, 'foo', 'test' => $foo, 'test' => &$foo, ...$var];", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test assign [] 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": OffsetLookup { + "kind": "offsetlookup", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "[]", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + "offset": false, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + }, + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var[] = $var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "name": "var", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var[] = $var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var[] = $var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test assign 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$var = true;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "true", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "raw": "true", + "value": true, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$var = true;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$var = true;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test assign by ref 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var = &$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$var", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "var", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var = &$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$var = &$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test assign mutliple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "$var = $other = true;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$other", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "name": "other", + }, + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "$other = true", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "operator": "=", + "right": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "true", + "start": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + }, + "raw": "true", + "value": true, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "$var = $other = true;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "$var = $other = true;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test bin 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "$var = $var + 100;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$var", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "$var + 100", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "100", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "value": "100", + }, + "type": "+", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "$var = $var + 100;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "$var = $var + 100;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test bin 2`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$var + 2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "2112", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "value": "2112", + }, + "type": "+", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$var + 2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$var + 2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test bin nested (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$var + $var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$var", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "name": "var", + }, + "type": "+", + }, + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var + $var + 2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "2112", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "value": "2112", + }, + "type": "+", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var + $var + 2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var + $var + 2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test bin nested 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$var + 2112", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "2112", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "value": "2112", + }, + "type": "+", + }, + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var + 2112 + $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "name": "var", + }, + "type": "+", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var + 2112 + $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var + 2112 + $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test break 1`] = ` +Program { + "children": [ + Break { + "kind": "break", + "level": null, + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "break;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "break;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test cast 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var = (int) "2112"", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Cast { + "expr": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": ""2112"", + "start": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + }, + "raw": ""2112"", + "unicode": false, + "value": "2112", + }, + "kind": "cast", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "(int) "2112"", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "raw": "(int)", + "type": "int", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var = (int) "2112"", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var = (int) "2112"", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test class (inner statement) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "class Foo {}", + "start": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 26, + "line": 1, + "offset": 26, + }, + "source": "Foo", + "start": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + }, + "name": "Foo", + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": "{ class Foo {} }", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + }, + "byref": false, + "kind": "function", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": "function foo()", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "foo", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": "function foo() { class Foo {} }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test class 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "class Foo {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "Foo", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "class Foo {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test clone 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Clone { + "kind": "clone", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "clone $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "$var", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "var", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "clone $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "clone $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test conststatement 1`] = ` +Program { + "children": [ + ConstantStatement { + "constants": [ + Constant { + "kind": "constant", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": "CONSTANT = "Hello world!"", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "CONSTANT", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": ""Hello world!"", + "start": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + }, + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + ], + "kind": "constantstatement", + "loc": Location { + "end": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + "source": "const CONSTANT = "Hello world!";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + "source": "const CONSTANT = "Hello world!";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test conststatement multiple 1`] = ` +Program { + "children": [ + ConstantStatement { + "constants": [ + Constant { + "kind": "constant", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": "CONSTANT = "Hello world!"", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "CONSTANT", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": ""Hello world!"", + "start": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + }, + "raw": ""Hello world!"", + "unicode": false, + "value": "Hello world!", + }, + }, + Constant { + "kind": "constant", + "loc": Location { + "end": Position { + "column": 70, + "line": 1, + "offset": 70, + }, + "source": "OTHER_CONSTANT = "Other hello world!"", + "start": Position { + "column": 33, + "line": 1, + "offset": 33, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 47, + "line": 1, + "offset": 47, + }, + "source": "OTHER_CONSTANT", + "start": Position { + "column": 33, + "line": 1, + "offset": 33, + }, + }, + "name": "OTHER_CONSTANT", + }, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 70, + "line": 1, + "offset": 70, + }, + "source": ""Other hello world!"", + "start": Position { + "column": 50, + "line": 1, + "offset": 50, + }, + }, + "raw": ""Other hello world!"", + "unicode": false, + "value": "Other hello world!", + }, + }, + ], + "kind": "constantstatement", + "loc": Location { + "end": Position { + "column": 71, + "line": 1, + "offset": 71, + }, + "source": "const CONSTANT = "Hello world!", OTHER_CONSTANT = "Other hello world!";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 71, + "line": 1, + "offset": 71, + }, + "source": "const CONSTANT = "Hello world!", OTHER_CONSTANT = "Other hello world!";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test continue 1`] = ` +Program { + "children": [ + Continue { + "kind": "continue", + "level": null, + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "continue;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "continue;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test declare 1`] = ` +Program { + "children": [ + Declare { + "children": [], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "ticks", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "ticks", + }, + "kind": "declaredirective", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "ticks=1", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "1", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "value": "1", + }, + }, + ], + "kind": "declare", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "declare(ticks=1);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "mode": "none", + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "declare(ticks=1);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test declare block 1`] = ` +Program { + "children": [ + Declare { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 35, + "line": 1, + "offset": 35, + }, + "source": ""something"", + "start": Position { + "column": 24, + "line": 1, + "offset": 24, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 36, + "line": 1, + "offset": 36, + }, + "source": "echo "something";", + "start": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + }, + "shortForm": false, + }, + ], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "ticks", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "ticks", + }, + "kind": "declaredirective", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "ticks=1", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "1", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "value": "1", + }, + }, + ], + "kind": "declare", + "loc": Location { + "end": Position { + "column": 38, + "line": 1, + "offset": 38, + }, + "source": "declare(ticks=1) { echo "something"; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "mode": "block", + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 38, + "line": 1, + "offset": 38, + }, + "source": "declare(ticks=1) { echo "something"; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test declare directive (multiple) 1`] = ` +Program { + "children": [ + Declare { + "children": [], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "A", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "name": "A", + }, + "kind": "declaredirective", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "A='B'", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "'B'", + "start": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + }, + "raw": "'B'", + "unicode": false, + "value": "B", + }, + }, + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "C", + "start": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + }, + "name": "C", + }, + "kind": "declaredirective", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "C='D'", + "start": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + }, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "'D'", + "start": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + }, + "raw": "'D'", + "unicode": false, + "value": "D", + }, + }, + ], + "kind": "declare", + "loc": Location { + "end": Position { + "column": 26, + "line": 1, + "offset": 26, + }, + "source": "declare (A='B', C='D') { }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "mode": "block", + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 26, + "line": 1, + "offset": 26, + }, + "source": "declare (A='B', C='D') { }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test declare directive 1`] = ` +Program { + "children": [ + Declare { + "children": [], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "strict_types", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "name": "strict_types", + }, + "kind": "declaredirective", + "loc": Location { + "end": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + "source": "strict_types=1", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + "source": "1", + "start": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + }, + "value": "1", + }, + }, + ], + "kind": "declare", + "loc": Location { + "end": Position { + "column": 25, + "line": 1, + "offset": 25, + }, + "source": "declare (strict_types=1);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "mode": "none", + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 25, + "line": 1, + "offset": 25, + }, + "source": "declare (strict_types=1);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test do 1`] = ` +Program { + "children": [ + Do { + "body": Block { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$i", + "start": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + }, + "name": "i", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "echo $i;", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "shortForm": false, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "{ echo $i; }", + "start": Position { + "column": 3, + "line": 1, + "offset": 3, + }, + }, + }, + "kind": "do", + "loc": Location { + "end": Position { + "column": 28, + "line": 1, + "offset": 28, + }, + "source": "do { echo $i; } while(true);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "test": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 26, + "line": 1, + "offset": 26, + }, + "source": "true", + "start": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + }, + "raw": "true", + "value": true, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 28, + "line": 1, + "offset": 28, + }, + "source": "do { echo $i; } while(true);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test echo 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + "source": ""something"", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "echo "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "echo "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test empty 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var = empty($var);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Empty { + "expression": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "$var", + "start": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + }, + "name": "var", + }, + "kind": "empty", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "empty($var)", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var = empty($var);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var = empty($var);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test encapsed heredoc 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "label": "EOD", + "loc": Location { + "end": Position { + "column": 4, + "line": 3, + "offset": 16, + }, + "source": "<< $b) echo "something"; elseif ($a < $b) echo "something"; else echo "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + "test": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "$a", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + "name": "a", + }, + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$a > $b", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$b", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "name": "b", + }, + "type": ">", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 88, + "line": 1, + "offset": 88, + }, + "source": "if ($a > $b) echo "something"; elseif ($a < $b) echo "something"; else echo "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test if/elseif/else block 1`] = ` +Program { + "children": [ + If { + "alternate": If { + "alternate": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 97, + "line": 1, + "offset": 97, + }, + "source": ""something"", + "start": Position { + "column": 86, + "line": 1, + "offset": 86, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 98, + "line": 1, + "offset": 98, + }, + "source": "echo "something";", + "start": Position { + "column": 81, + "line": 1, + "offset": 81, + }, + }, + "shortForm": false, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 100, + "line": 1, + "offset": 100, + }, + "source": "{ echo "something"; }", + "start": Position { + "column": 79, + "line": 1, + "offset": 79, + }, + }, + }, + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 70, + "line": 1, + "offset": 70, + }, + "source": ""something"", + "start": Position { + "column": 59, + "line": 1, + "offset": 59, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 71, + "line": 1, + "offset": 71, + }, + "source": "echo "something";", + "start": Position { + "column": 54, + "line": 1, + "offset": 54, + }, + }, + "shortForm": false, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 73, + "line": 1, + "offset": 73, + }, + "source": "{ echo "something"; }", + "start": Position { + "column": 52, + "line": 1, + "offset": 52, + }, + }, + }, + "kind": "if", + "loc": Location { + "end": Position { + "column": 100, + "line": 1, + "offset": 100, + }, + "source": "elseif ($a < $b) { echo "something"; } else { echo "something"; }", + "start": Position { + "column": 35, + "line": 1, + "offset": 35, + }, + }, + "shortForm": false, + "test": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 45, + "line": 1, + "offset": 45, + }, + "source": "$a", + "start": Position { + "column": 43, + "line": 1, + "offset": 43, + }, + }, + "name": "a", + }, + "loc": Location { + "end": Position { + "column": 50, + "line": 1, + "offset": 50, + }, + "source": "$a < $b", + "start": Position { + "column": 43, + "line": 1, + "offset": 43, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 50, + "line": 1, + "offset": 50, + }, + "source": "$b", + "start": Position { + "column": 48, + "line": 1, + "offset": 48, + }, + }, + "name": "b", + }, + "type": "<", + }, + }, + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": ""something"", + "start": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + "source": "echo "something";", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + "shortForm": false, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 34, + "line": 1, + "offset": 34, + }, + "source": "{ echo "something"; }", + "start": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + }, + }, + "kind": "if", + "loc": Location { + "end": Position { + "column": 100, + "line": 1, + "offset": 100, + }, + "source": "if ($a > $b) { echo "something"; } elseif ($a < $b) { echo "something"; } else { echo "something"; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + "test": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "$a", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + "name": "a", + }, + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$a > $b", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$b", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "name": "b", + }, + "type": ">", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 100, + "line": 1, + "offset": 100, + }, + "source": "if ($a > $b) { echo "something"; } elseif ($a < $b) { echo "something"; } else { echo "something"; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test include 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Include { + "kind": "include", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "include "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "once": false, + "require": false, + "target": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": ""something"", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "include "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "include "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test interface 1`] = ` +Program { + "children": [ + Interface { + "attrGroups": [], + "body": [], + "extends": null, + "kind": "interface", + "loc": Location { + "end": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + "source": "interface Foo {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "Foo", + "start": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + }, + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + "source": "interface Foo {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test isset 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var = isset($var);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Isset { + "kind": "isset", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "isset($var)", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "$var", + "start": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + }, + "name": "var", + }, + ], + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var = isset($var);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var = isset($var);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test label #2 1`] = ` +Program { + "children": [ + Label { + "kind": "label", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "longName:", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "longName", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "longName", + }, + }, + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 26, + "line": 1, + "offset": 26, + }, + "source": ""something"", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 27, + "line": 1, + "offset": 27, + }, + "source": "echo "something";", + "start": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + }, + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 27, + "line": 1, + "offset": 27, + }, + "source": "longName: echo "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test label 1`] = ` +Program { + "children": [ + Label { + "kind": "label", + "loc": Location { + "end": Position { + "column": 2, + "line": 1, + "offset": 2, + }, + "source": "a:", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + "source": "a", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "a", + }, + }, + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": ""something"", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "echo "something";", + "start": Position { + "column": 3, + "line": 1, + "offset": 3, + }, + }, + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "a: echo "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test list 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "$a", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "$a", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "name": "a", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$b", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$b", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "name": "b", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "$c", + "start": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "$c", + "start": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + }, + "name": "c", + }, + }, + ], + "kind": "list", + "loc": Location { + "end": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + "source": "list($a, $b, $c)", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + }, + "loc": Location { + "end": Position { + "column": 24, + "line": 1, + "offset": 24, + }, + "source": "list($a, $b, $c) = $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + "source": "$var", + "start": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + }, + "name": "var", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 24, + "line": 1, + "offset": 24, + }, + "source": "list($a, $b, $c) = $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 24, + "line": 1, + "offset": 24, + }, + "source": "list($a, $b, $c) = $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test list short form 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 3, + "line": 1, + "offset": 3, + }, + "source": "$a", + "start": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 3, + "line": 1, + "offset": 3, + }, + "source": "$a", + "start": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + }, + "name": "a", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "$b", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "$b", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "name": "b", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$c", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$c", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "name": "c", + }, + }, + ], + "kind": "list", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "[$a, $b, $c]", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": true, + }, + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "[$a, $b, $c] = $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "$var", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + "name": "var", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "[$a, $b, $c] = $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "[$a, $b, $c] = $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test magic 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "__DIR__;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "raw": "__DIR__", + "value": "__DIR__", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "__DIR__;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "__DIR__;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test method (public) 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + "loc": Location { + "end": Position { + "column": 39, + "line": 1, + "offset": 39, + }, + "source": "{}", + "start": Position { + "column": 37, + "line": 1, + "offset": 37, + }, + }, + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 39, + "line": 1, + "offset": 39, + }, + "source": "public function method()", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 34, + "line": 1, + "offset": 34, + }, + "source": "method", + "start": Position { + "column": 28, + "line": 1, + "offset": 28, + }, + }, + "name": "method", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 41, + "line": 1, + "offset": 41, + }, + "source": "class Foo { public function method() {} }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "Foo", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 41, + "line": 1, + "offset": 41, + }, + "source": "class Foo { public function method() {} }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test method 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + "loc": Location { + "end": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + "source": "{}", + "start": Position { + "column": 30, + "line": 1, + "offset": 30, + }, + }, + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + "source": "function method()", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 27, + "line": 1, + "offset": 27, + }, + "source": "method", + "start": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + }, + "name": "method", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 34, + "line": 1, + "offset": 34, + }, + "source": "class Foo { function method() {} }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "Foo", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 34, + "line": 1, + "offset": 34, + }, + "source": "class Foo { function method() {} }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test namespace 1`] = ` +Program { + "children": [ + Namespace { + "children": [], + "kind": "namespace", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "namespace my\\name;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "my\\name", + "withBrackets": false, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "namespace my\\name;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test namespace backets 1`] = ` +Program { + "children": [ + Namespace { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 36, + "line": 1, + "offset": 36, + }, + "source": ""something"", + "start": Position { + "column": 25, + "line": 1, + "offset": 25, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 37, + "line": 1, + "offset": 37, + }, + "source": "echo "something";", + "start": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + }, + "shortForm": false, + }, + ], + "kind": "namespace", + "loc": Location { + "end": Position { + "column": 39, + "line": 1, + "offset": 39, + }, + "source": "namespace my\\name { echo "something"; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "my\\name", + "withBrackets": true, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 39, + "line": 1, + "offset": 39, + }, + "source": "namespace my\\name { echo "something"; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test negative number 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "-2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "type": "-", + "what": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "2112", + "start": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + }, + "value": "2112", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "-2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "-2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test new 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "new Foo();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "Foo", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + "name": "Foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "new Foo();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "new Foo();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test new anonymous class 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "$var = new class {};", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": New { + "arguments": [], + "kind": "new", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "new class {}", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "what": Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "class {}", + "start": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + }, + "name": null, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "$var = new class {};", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "$var = new class {};", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test nowdoc 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Nowdoc { + "kind": "nowdoc", + "label": "EOD", + "loc": Location { + "end": Position { + "column": 4, + "line": 3, + "offset": 18, + }, + "source": "<<<'EOD' +Text +EOD;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "raw": "<<<'EOD' +Text +EOD", + "value": "Text", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 4, + "line": 3, + "offset": 18, + }, + "source": "<<<'EOD' +Text +EOD;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 4, + "line": 3, + "offset": 18, + }, + "source": "<<<'EOD' +Text +EOD;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test nowdoc assign 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 4, + "line": 3, + "offset": 25, + }, + "source": "$var = <<<'EOD' +Text +EOD;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Nowdoc { + "kind": "nowdoc", + "label": "EOD", + "loc": Location { + "end": Position { + "column": 3, + "line": 3, + "offset": 24, + }, + "source": "<<<'EOD' +Text +EOD", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "raw": "<<<'EOD' +Text +EOD", + "value": "Text", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 4, + "line": 3, + "offset": 25, + }, + "source": "$var = <<<'EOD' +Text +EOD;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 4, + "line": 3, + "offset": 25, + }, + "source": "$var = <<<'EOD' +Text +EOD;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test number 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "value": "2112", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "2112;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test offsetlookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 2, + "offset": 13, + }, + "source": "$var", + "start": Position { + "column": 8, + "line": 2, + "offset": 9, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 18, + "line": 10, + "offset": 212, + }, + "source": "$var = $var + // Comment + [ 'foo' ] // Comment + // Comment + ['bar'] // Comment + // Comment + ['baz'] // Comment + // Comment + ['qqq'];", + "start": Position { + "column": 8, + "line": 2, + "offset": 9, + }, + }, + "operator": "=", + "right": OffsetLookup { + "kind": "offsetlookup", + "loc": Location { + "end": Position { + "column": 17, + "line": 10, + "offset": 211, + }, + "source": "$var + // Comment + [ 'foo' ] // Comment + // Comment + ['bar'] // Comment + // Comment + ['baz'] // Comment + // Comment + ['qqq']", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 16, + "line": 10, + "offset": 210, + }, + "source": "'qqq'", + "start": Position { + "column": 11, + "line": 10, + "offset": 205, + }, + }, + "raw": "'qqq'", + "unicode": false, + "value": "qqq", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "loc": Location { + "end": Position { + "column": 17, + "line": 8, + "offset": 161, + }, + "source": "$var + // Comment + [ 'foo' ] // Comment + // Comment + ['bar'] // Comment + // Comment + ['baz']", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 16, + "line": 8, + "offset": 160, + }, + "source": "'baz'", + "start": Position { + "column": 11, + "line": 8, + "offset": 155, + }, + }, + "raw": "'baz'", + "unicode": false, + "value": "baz", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "loc": Location { + "end": Position { + "column": 17, + "line": 6, + "offset": 111, + }, + "source": "$var + // Comment + [ 'foo' ] // Comment + // Comment + ['bar']", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 16, + "line": 6, + "offset": 110, + }, + "source": "'bar'", + "start": Position { + "column": 11, + "line": 6, + "offset": 105, + }, + }, + "raw": "'bar'", + "unicode": false, + "value": "bar", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "loc": Location { + "end": Position { + "column": 19, + "line": 4, + "offset": 61, + }, + "source": "$var + // Comment + [ 'foo' ]", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 17, + "line": 4, + "offset": 59, + }, + "source": "'foo'", + "start": Position { + "column": 12, + "line": 4, + "offset": 54, + }, + }, + "raw": "'foo'", + "unicode": false, + "value": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 2, + "offset": 20, + }, + "source": "$var", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "name": "var", + }, + }, + }, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 18, + "line": 10, + "offset": 212, + }, + "source": "$var = $var + // Comment + [ 'foo' ] // Comment + // Comment + ['bar'] // Comment + // Comment + ['baz'] // Comment + // Comment + ['qqq'];", + "start": Position { + "column": 8, + "line": 2, + "offset": 9, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 8, + "line": 11, + "offset": 221, + }, + "source": " + $var = $var + // Comment + [ 'foo' ] // Comment + // Comment + ['bar'] // Comment + // Comment + ['baz'] // Comment + // Comment + ['qqq']; + ", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test parameter 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "?int $foo = 2112", + "start": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "$foo", + "start": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + }, + "name": "foo", + }, + "nullable": true, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "int", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "name": "int", + "raw": "int", + }, + "value": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "2112", + "start": Position { + "column": 25, + "line": 1, + "offset": 25, + }, + }, + "value": "2112", + }, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + "loc": Location { + "end": Position { + "column": 33, + "line": 1, + "offset": 33, + }, + "source": "{}", + "start": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + }, + }, + "byref": false, + "kind": "function", + "loc": Location { + "end": Position { + "column": 33, + "line": 1, + "offset": 33, + }, + "source": "function foo(?int $foo = 2112)", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "foo", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 33, + "line": 1, + "offset": 33, + }, + "source": "function foo(?int $foo = 2112) {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test post 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Post { + "kind": "post", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "$var++;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "$var++;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "$var++;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test pre 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Pre { + "kind": "pre", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "++$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "$var", + "start": Position { + "column": 2, + "line": 1, + "offset": 2, + }, + }, + "name": "var", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "++$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "++$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test print 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Print { + "expression": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": ""something"", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + "kind": "print", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "print "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "print "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "print "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test propertylookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 2, + "offset": 13, + }, + "source": "$var", + "start": Position { + "column": 8, + "line": 2, + "offset": 9, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 19, + "line": 10, + "offset": 214, + }, + "source": "$var = $var + // Comment + ->each() // Comment + // Comment + ->map() // Comment + // Comment + ->first() // Comment + // Comment + ->dump();", + "start": Position { + "column": 8, + "line": 2, + "offset": 9, + }, + }, + "operator": "=", + "right": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 18, + "line": 10, + "offset": 213, + }, + "source": "$var + // Comment + ->each() // Comment + // Comment + ->map() // Comment + // Comment + ->first() // Comment + // Comment + ->dump()", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 16, + "line": 10, + "offset": 211, + }, + "source": "$var + // Comment + ->each() // Comment + // Comment + ->map() // Comment + // Comment + ->first() // Comment + // Comment + ->dump", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 16, + "line": 10, + "offset": 211, + }, + "source": "dump", + "start": Position { + "column": 12, + "line": 10, + "offset": 207, + }, + }, + "name": "dump", + }, + "what": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 19, + "line": 8, + "offset": 162, + }, + "source": "$var + // Comment + ->each() // Comment + // Comment + ->map() // Comment + // Comment + ->first()", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 17, + "line": 8, + "offset": 160, + }, + "source": "$var + // Comment + ->each() // Comment + // Comment + ->map() // Comment + // Comment + ->first", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 17, + "line": 8, + "offset": 160, + }, + "source": "first", + "start": Position { + "column": 12, + "line": 8, + "offset": 155, + }, + }, + "name": "first", + }, + "what": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 17, + "line": 6, + "offset": 110, + }, + "source": "$var + // Comment + ->each() // Comment + // Comment + ->map()", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 15, + "line": 6, + "offset": 108, + }, + "source": "$var + // Comment + ->each() // Comment + // Comment + ->map", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 15, + "line": 6, + "offset": 108, + }, + "source": "map", + "start": Position { + "column": 12, + "line": 6, + "offset": 105, + }, + }, + "name": "map", + }, + "what": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 18, + "line": 4, + "offset": 60, + }, + "source": "$var + // Comment + ->each()", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "loc": Location { + "end": Position { + "column": 16, + "line": 4, + "offset": 58, + }, + "source": "$var + // Comment + ->each", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 16, + "line": 4, + "offset": 58, + }, + "source": "each", + "start": Position { + "column": 12, + "line": 4, + "offset": 54, + }, + }, + "name": "each", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 2, + "offset": 20, + }, + "source": "$var", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "name": "var", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 19, + "line": 10, + "offset": 214, + }, + "source": "$var = $var + // Comment + ->each() // Comment + // Comment + ->map() // Comment + // Comment + ->first() // Comment + // Comment + ->dump();", + "start": Position { + "column": 8, + "line": 2, + "offset": 9, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 8, + "line": 11, + "offset": 223, + }, + "source": " + $var = $var + // Comment + ->each() // Comment + // Comment + ->map() // Comment + // Comment + ->first() // Comment + // Comment + ->dump(); + ", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test retif 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 27, + "line": 1, + "offset": 27, + }, + "source": "$var = $var ? true : false;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": RetIf { + "falseExpr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 26, + "line": 1, + "offset": 26, + }, + "source": "false", + "start": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + }, + "raw": "false", + "value": false, + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 26, + "line": 1, + "offset": 26, + }, + "source": "$var ? true : false", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "$var", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "name": "var", + }, + "trueExpr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "true", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "raw": "true", + "value": true, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 27, + "line": 1, + "offset": 27, + }, + "source": "$var = $var ? true : false;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 27, + "line": 1, + "offset": 27, + }, + "source": "$var = $var ? true : false;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test retif nested 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 79, + "line": 1, + "offset": 79, + }, + "source": "$var = ($one ? true : false) ? ($two ? true : false) : ($three ? true : false);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": RetIf { + "falseExpr": RetIf { + "falseExpr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 77, + "line": 1, + "offset": 77, + }, + "source": "false", + "start": Position { + "column": 72, + "line": 1, + "offset": 72, + }, + }, + "raw": "false", + "value": false, + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 77, + "line": 1, + "offset": 77, + }, + "source": "$three ? true : false", + "start": Position { + "column": 56, + "line": 1, + "offset": 56, + }, + }, + "parenthesizedExpression": true, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 62, + "line": 1, + "offset": 62, + }, + "source": "$three", + "start": Position { + "column": 56, + "line": 1, + "offset": 56, + }, + }, + "name": "three", + }, + "trueExpr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 69, + "line": 1, + "offset": 69, + }, + "source": "true", + "start": Position { + "column": 65, + "line": 1, + "offset": 65, + }, + }, + "raw": "true", + "value": true, + }, + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 78, + "line": 1, + "offset": 78, + }, + "source": "($one ? true : false) ? ($two ? true : false) : ($three ? true : false)", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "test": RetIf { + "falseExpr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 27, + "line": 1, + "offset": 27, + }, + "source": "false", + "start": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + }, + "raw": "false", + "value": false, + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 27, + "line": 1, + "offset": 27, + }, + "source": "$one ? true : false", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "parenthesizedExpression": true, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$one", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "one", + }, + "trueExpr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + "source": "true", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + "raw": "true", + "value": true, + }, + }, + "trueExpr": RetIf { + "falseExpr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 51, + "line": 1, + "offset": 51, + }, + "source": "false", + "start": Position { + "column": 46, + "line": 1, + "offset": 46, + }, + }, + "raw": "false", + "value": false, + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 51, + "line": 1, + "offset": 51, + }, + "source": "$two ? true : false", + "start": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + }, + "parenthesizedExpression": true, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 36, + "line": 1, + "offset": 36, + }, + "source": "$two", + "start": Position { + "column": 32, + "line": 1, + "offset": 32, + }, + }, + "name": "two", + }, + "trueExpr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 43, + "line": 1, + "offset": 43, + }, + "source": "true", + "start": Position { + "column": 39, + "line": 1, + "offset": 39, + }, + }, + "raw": "true", + "value": true, + }, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 79, + "line": 1, + "offset": 79, + }, + "source": "$var = ($one ? true : false) ? ($two ? true : false) : ($three ? true : false);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 79, + "line": 1, + "offset": 79, + }, + "source": "$var = ($one ? true : false) ? ($two ? true : false) : ($three ? true : false);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test return 1`] = ` +Program { + "children": [ + Return { + "expr": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "1", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "value": "1", + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "return 1;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "return 1;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test silent 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "$var", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "$var = @call();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "operator": "=", + "right": Silent { + "expr": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "call()", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "call", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "silent", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "@call()", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "$var = @call();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "$var = @call();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test silent 2`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Silent { + "expr": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "call()", + "start": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "call", + "start": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + }, + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "silent", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "@call();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "@call();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + "source": "@call();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test single call 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "call();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "call", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "call();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + "source": "call();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test static 1`] = ` +Program { + "children": [ + Static { + "kind": "static", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "static $a = 1;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "variables": [ + StaticVariable { + "defaultValue": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "1", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "value": "1", + }, + "kind": "staticvariable", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$a = 1", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "variable": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "$a", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "name": "a", + }, + }, + ], + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "static $a = 1;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test static multiple 1`] = ` +Program { + "children": [ + Static { + "kind": "static", + "loc": Location { + "end": Position { + "column": 30, + "line": 1, + "offset": 30, + }, + "source": "static $a = 1, $b = 2, $c = 3;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "variables": [ + StaticVariable { + "defaultValue": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "1", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "value": "1", + }, + "kind": "staticvariable", + "loc": Location { + "end": Position { + "column": 13, + "line": 1, + "offset": 13, + }, + "source": "$a = 1", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "variable": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "$a", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "name": "a", + }, + }, + StaticVariable { + "defaultValue": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "2", + "start": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + }, + "value": "2", + }, + "kind": "staticvariable", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "$b = 2", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + "variable": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "$b", + "start": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + }, + "name": "b", + }, + }, + StaticVariable { + "defaultValue": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "3", + "start": Position { + "column": 28, + "line": 1, + "offset": 28, + }, + }, + "value": "3", + }, + "kind": "staticvariable", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "$c = 3", + "start": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + }, + "variable": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 25, + "line": 1, + "offset": 25, + }, + "source": "$c", + "start": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + }, + "name": "c", + }, + }, + ], + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 30, + "line": 1, + "offset": 30, + }, + "source": "static $a = 1, $b = 2, $c = 3;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test staticlookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 2, + "offset": 13, + }, + "source": "$var", + "start": Position { + "column": 8, + "line": 2, + "offset": 9, + }, + }, + "name": "var", + }, + "loc": Location { + "end": Position { + "column": 19, + "line": 10, + "offset": 214, + }, + "source": "$var = $var + // Comment + ::each() // Comment + // Comment + ::map() // Comment + // Comment + ::first() // Comment + // Comment + ::dump();", + "start": Position { + "column": 8, + "line": 2, + "offset": 9, + }, + }, + "operator": "=", + "right": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 18, + "line": 10, + "offset": 213, + }, + "source": "$var + // Comment + ::each() // Comment + // Comment + ::map() // Comment + // Comment + ::first() // Comment + // Comment + ::dump()", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "what": StaticLookup { + "kind": "staticlookup", + "loc": Location { + "end": Position { + "column": 16, + "line": 10, + "offset": 211, + }, + "source": "$var + // Comment + ::each() // Comment + // Comment + ::map() // Comment + // Comment + ::first() // Comment + // Comment + ::dump", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 16, + "line": 10, + "offset": 211, + }, + "source": "dump", + "start": Position { + "column": 12, + "line": 10, + "offset": 207, + }, + }, + "name": "dump", + }, + "what": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 19, + "line": 8, + "offset": 162, + }, + "source": "$var + // Comment + ::each() // Comment + // Comment + ::map() // Comment + // Comment + ::first()", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "what": StaticLookup { + "kind": "staticlookup", + "loc": Location { + "end": Position { + "column": 17, + "line": 8, + "offset": 160, + }, + "source": "$var + // Comment + ::each() // Comment + // Comment + ::map() // Comment + // Comment + ::first", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 17, + "line": 8, + "offset": 160, + }, + "source": "first", + "start": Position { + "column": 12, + "line": 8, + "offset": 155, + }, + }, + "name": "first", + }, + "what": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 17, + "line": 6, + "offset": 110, + }, + "source": "$var + // Comment + ::each() // Comment + // Comment + ::map()", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "what": StaticLookup { + "kind": "staticlookup", + "loc": Location { + "end": Position { + "column": 15, + "line": 6, + "offset": 108, + }, + "source": "$var + // Comment + ::each() // Comment + // Comment + ::map", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 15, + "line": 6, + "offset": 108, + }, + "source": "map", + "start": Position { + "column": 12, + "line": 6, + "offset": 105, + }, + }, + "name": "map", + }, + "what": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 18, + "line": 4, + "offset": 60, + }, + "source": "$var + // Comment + ::each()", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "what": StaticLookup { + "kind": "staticlookup", + "loc": Location { + "end": Position { + "column": 16, + "line": 4, + "offset": 58, + }, + "source": "$var + // Comment + ::each", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "offset": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 16, + "line": 4, + "offset": 58, + }, + "source": "each", + "start": Position { + "column": 12, + "line": 4, + "offset": 54, + }, + }, + "name": "each", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 2, + "offset": 20, + }, + "source": "$var", + "start": Position { + "column": 15, + "line": 2, + "offset": 16, + }, + }, + "name": "var", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 19, + "line": 10, + "offset": 214, + }, + "source": "$var = $var + // Comment + ::each() // Comment + // Comment + ::map() // Comment + // Comment + ::first() // Comment + // Comment + ::dump();", + "start": Position { + "column": 8, + "line": 2, + "offset": 9, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 8, + "line": 11, + "offset": 223, + }, + "source": " + $var = $var + // Comment + ::each() // Comment + // Comment + ::map() // Comment + // Comment + ::first() // Comment + // Comment + ::dump(); + ", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test string double quotes 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": ""string";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "raw": ""string"", + "unicode": false, + "value": "string", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": ""string";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": ""string";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test string single quotes 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "'string';", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "raw": "'string'", + "unicode": false, + "value": "string", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "'string';", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "'string';", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test switch 1`] = ` +Program { + "children": [ + Switch { + "body": Block { + "children": [], + "kind": "block", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "{}", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + }, + "kind": "switch", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "switch ($i) {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "$i", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "i", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "switch ($i) {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test switch case 1`] = ` +Program { + "children": [ + Switch { + "body": Block { + "children": [ + Case { + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 38, + "line": 1, + "offset": 38, + }, + "source": ""something"", + "start": Position { + "column": 27, + "line": 1, + "offset": 27, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 39, + "line": 1, + "offset": 39, + }, + "source": "echo "something";", + "start": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + }, + "shortForm": false, + }, + Break { + "kind": "break", + "level": null, + "loc": Location { + "end": Position { + "column": 46, + "line": 1, + "offset": 46, + }, + "source": "break;", + "start": Position { + "column": 40, + "line": 1, + "offset": 40, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 46, + "line": 1, + "offset": 46, + }, + "source": "echo "something"; break;", + "start": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + }, + }, + "kind": "case", + "loc": Location { + "end": Position { + "column": 46, + "line": 1, + "offset": 46, + }, + "source": "case 0: echo "something"; break;", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "test": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "0", + "start": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + }, + "value": "0", + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 48, + "line": 1, + "offset": 48, + }, + "source": "{ case 0: echo "something"; break; }", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + }, + "kind": "switch", + "loc": Location { + "end": Position { + "column": 48, + "line": 1, + "offset": 48, + }, + "source": "switch ($i) { case 0: echo "something"; break; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "$i", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "i", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 48, + "line": 1, + "offset": 48, + }, + "source": "switch ($i) { case 0: echo "something"; break; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test switch default 1`] = ` +Program { + "children": [ + Switch { + "body": Block { + "children": [ + Case { + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 39, + "line": 1, + "offset": 39, + }, + "source": ""something"", + "start": Position { + "column": 28, + "line": 1, + "offset": 28, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 40, + "line": 1, + "offset": 40, + }, + "source": "echo "something";", + "start": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + }, + "shortForm": false, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 40, + "line": 1, + "offset": 40, + }, + "source": "echo "something";", + "start": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + }, + }, + "kind": "case", + "loc": Location { + "end": Position { + "column": 40, + "line": 1, + "offset": 40, + }, + "source": "default: echo "something";", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "test": null, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 42, + "line": 1, + "offset": 42, + }, + "source": "{ default: echo "something"; }", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + }, + "kind": "switch", + "loc": Location { + "end": Position { + "column": 42, + "line": 1, + "offset": 42, + }, + "source": "switch ($i) { default: echo "something"; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "$i", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "i", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 42, + "line": 1, + "offset": 42, + }, + "source": "switch ($i) { default: echo "something"; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test ternary 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": RetIf { + "falseExpr": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": ""no"", + "start": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + }, + "raw": ""no"", + "unicode": false, + "value": "no", + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "$valid ? "yes" : "no";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "$valid", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "valid", + }, + "trueExpr": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": ""yes"", + "start": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + }, + "raw": ""yes"", + "unicode": false, + "value": "yes", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "$valid ? "yes" : "no";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "$valid ? "yes" : "no";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test ternary no true expression 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": RetIf { + "falseExpr": String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": ""no"", + "start": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + }, + "raw": ""no"", + "unicode": false, + "value": "no", + }, + "kind": "retif", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "$valid ?: "no";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "test": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "$valid", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "valid", + }, + "trueExpr": null, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "$valid ?: "no";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "$valid ?: "no";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test trait 1`] = ` +Program { + "children": [ + Trait { + "body": [], + "kind": "trait", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "trait Foo {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "Foo", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "trait Foo {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test traituse 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + TraitUse { + "adaptations": null, + "kind": "traituse", + "loc": Location { + "end": Position { + "column": 22, + "line": 1, + "offset": 22, + }, + "source": "use Hello;", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "traits": [ + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "Hello", + "start": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + }, + "name": "Hello", + "resolution": "uqn", + }, + ], + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 24, + "line": 1, + "offset": 24, + }, + "source": "class Foo { use Hello; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "Foo", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 24, + "line": 1, + "offset": 24, + }, + "source": "class Foo { use Hello; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test traituse adaptations 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + TraitUse { + "adaptations": [ + TraitPrecedence { + "instead": [ + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 47, + "line": 1, + "offset": 47, + }, + "source": "A", + "start": Position { + "column": 46, + "line": 1, + "offset": 46, + }, + }, + "name": "A", + "resolution": "uqn", + }, + ], + "kind": "traitprecedence", + "loc": Location { + "end": Position { + "column": 47, + "line": 1, + "offset": 47, + }, + "source": "B::smallTalk insteadof A", + "start": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + }, + "method": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 35, + "line": 1, + "offset": 35, + }, + "source": "smallTalk", + "start": Position { + "column": 26, + "line": 1, + "offset": 26, + }, + }, + "name": "smallTalk", + }, + "trait": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 24, + "line": 1, + "offset": 24, + }, + "source": "B", + "start": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + }, + "name": "B", + "resolution": "uqn", + }, + }, + TraitAlias { + "as": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 68, + "line": 1, + "offset": 68, + }, + "source": "talk", + "start": Position { + "column": 64, + "line": 1, + "offset": 64, + }, + }, + "name": "talk", + }, + "kind": "traitalias", + "loc": Location { + "end": Position { + "column": 68, + "line": 1, + "offset": 68, + }, + "source": "B::bigTalk as talk", + "start": Position { + "column": 50, + "line": 1, + "offset": 50, + }, + }, + "method": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 60, + "line": 1, + "offset": 60, + }, + "source": "bigTalk", + "start": Position { + "column": 53, + "line": 1, + "offset": 53, + }, + }, + "name": "bigTalk", + }, + "trait": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 51, + "line": 1, + "offset": 51, + }, + "source": "B", + "start": Position { + "column": 50, + "line": 1, + "offset": 50, + }, + }, + "name": "B", + "resolution": "uqn", + }, + "visibility": "", + }, + TraitAlias { + "as": null, + "kind": "traitalias", + "loc": Location { + "end": Position { + "column": 91, + "line": 1, + "offset": 91, + }, + "source": "sayHello as protected", + "start": Position { + "column": 70, + "line": 1, + "offset": 70, + }, + }, + "method": "sayHello", + "trait": null, + "visibility": "protected", + }, + TraitAlias { + "as": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 127, + "line": 1, + "offset": 127, + }, + "source": "myPrivateHello", + "start": Position { + "column": 113, + "line": 1, + "offset": 113, + }, + }, + "name": "myPrivateHello", + }, + "kind": "traitalias", + "loc": Location { + "end": Position { + "column": 127, + "line": 1, + "offset": 127, + }, + "source": "sayHello as private myPrivateHello", + "start": Position { + "column": 93, + "line": 1, + "offset": 93, + }, + }, + "method": "sayHello", + "trait": null, + "visibility": "private", + }, + ], + "kind": "traituse", + "loc": Location { + "end": Position { + "column": 130, + "line": 1, + "offset": 130, + }, + "source": "use A, B { B::smallTalk insteadof A; B::bigTalk as talk; sayHello as protected; sayHello as private myPrivateHello; }", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "traits": [ + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "A", + "start": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + }, + "name": "A", + "resolution": "uqn", + }, + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "B", + "start": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + }, + "name": "B", + "resolution": "uqn", + }, + ], + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 132, + "line": 1, + "offset": 132, + }, + "source": "class Foo { use A, B { B::smallTalk insteadof A; B::bigTalk as talk; sayHello as protected; sayHello as private myPrivateHello; } }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "Foo", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 132, + "line": 1, + "offset": 132, + }, + "source": "class Foo { use A, B { B::smallTalk insteadof A; B::bigTalk as talk; sayHello as protected; sayHello as private myPrivateHello; } }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test traituse multiple 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + TraitUse { + "adaptations": null, + "kind": "traituse", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "use Hello, World;", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "traits": [ + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 21, + "line": 1, + "offset": 21, + }, + "source": "Hello", + "start": Position { + "column": 16, + "line": 1, + "offset": 16, + }, + }, + "name": "Hello", + "resolution": "uqn", + }, + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 28, + "line": 1, + "offset": 28, + }, + "source": "World", + "start": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + }, + "name": "World", + "resolution": "uqn", + }, + ], + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": "class Foo { use Hello, World; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 9, + "line": 1, + "offset": 9, + }, + "source": "Foo", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": "class Foo { use Hello, World; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test try 1`] = ` +Program { + "children": [ + Try { + "always": null, + "body": ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "new Exception();", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "Exception", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "Exception", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "new Exception();", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + }, + "catches": [], + "kind": "try", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "try new Exception();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 20, + "line": 1, + "offset": 20, + }, + "source": "try new Exception();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test try/catch/finally 1`] = ` +Program { + "children": [ + Try { + "always": Block { + "children": [], + "kind": "block", + "loc": Location { + "end": Position { + "column": 41, + "line": 1, + "offset": 41, + }, + "source": "{}", + "start": Position { + "column": 39, + "line": 1, + "offset": 39, + }, + }, + }, + "body": Block { + "children": [], + "kind": "block", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "{}", + "start": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + }, + }, + "catches": [ + Catch { + "body": Block { + "children": [], + "kind": "block", + "loc": Location { + "end": Position { + "column": 30, + "line": 1, + "offset": 30, + }, + "source": "{}", + "start": Position { + "column": 28, + "line": 1, + "offset": 28, + }, + }, + }, + "kind": "catch", + "loc": Location { + "end": Position { + "column": 30, + "line": 1, + "offset": 30, + }, + "source": "catch (Exception $e) {}", + "start": Position { + "column": 7, + "line": 1, + "offset": 7, + }, + }, + "variable": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 26, + "line": 1, + "offset": 26, + }, + "source": "$e", + "start": Position { + "column": 24, + "line": 1, + "offset": 24, + }, + }, + "name": "e", + }, + "what": [ + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 23, + "line": 1, + "offset": 23, + }, + "source": "Exception", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "name": "Exception", + "resolution": "uqn", + }, + ], + }, + ], + "kind": "try", + "loc": Location { + "end": Position { + "column": 41, + "line": 1, + "offset": 41, + }, + "source": "try {} catch (Exception $e) {} finally {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 41, + "line": 1, + "offset": 41, + }, + "source": "try {} catch (Exception $e) {} finally {}", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test unary 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "!$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "type": "!", + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "$var", + "start": Position { + "column": 1, + "line": 1, + "offset": 1, + }, + }, + "name": "var", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "!$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + "source": "!$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test unset 1`] = ` +Program { + "children": [ + Unset { + "kind": "unset", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "unset($foo);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "$foo", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "foo", + }, + ], + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "unset($foo);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "var", + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + "source": "$var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test variadic 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + variadic { + "kind": "variadic", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "...$var", + "start": Position { + "column": 5, + "line": 1, + "offset": 5, + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + "source": "$var", + "start": Position { + "column": 8, + "line": 1, + "offset": 8, + }, + }, + "name": "var", + }, + }, + ], + "kind": "call", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "call(...$var);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 4, + "line": 1, + "offset": 4, + }, + "source": "call", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "call(...$var);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + "source": "call(...$var);", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test while 1`] = ` +Program { + "children": [ + While { + "body": Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 28, + "line": 1, + "offset": 28, + }, + "source": ""something"", + "start": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "echo "something";", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + "shortForm": false, + }, + "kind": "while", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "while(true) echo "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "true", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "raw": "true", + "value": true, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 29, + "line": 1, + "offset": 29, + }, + "source": "while(true) echo "something";", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test while block 1`] = ` +Program { + "children": [ + While { + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "loc": Location { + "end": Position { + "column": 30, + "line": 1, + "offset": 30, + }, + "source": ""something"", + "start": Position { + "column": 19, + "line": 1, + "offset": 19, + }, + }, + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "loc": Location { + "end": Position { + "column": 31, + "line": 1, + "offset": 31, + }, + "source": "echo "something";", + "start": Position { + "column": 14, + "line": 1, + "offset": 14, + }, + }, + "shortForm": false, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 33, + "line": 1, + "offset": 33, + }, + "source": "{ echo "something"; }", + "start": Position { + "column": 12, + "line": 1, + "offset": 12, + }, + }, + }, + "kind": "while", + "loc": Location { + "end": Position { + "column": 33, + "line": 1, + "offset": 33, + }, + "source": "while(true) { echo "something"; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "true", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "raw": "true", + "value": true, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 33, + "line": 1, + "offset": 33, + }, + "source": "while(true) { echo "something"; }", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test yield 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Yield { + "key": null, + "kind": "yield", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "yield $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "value": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 10, + "line": 1, + "offset": 10, + }, + "source": "$var", + "start": Position { + "column": 6, + "line": 1, + "offset": 6, + }, + }, + "name": "var", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "yield $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + "source": "yield $var;", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test locations test yield from 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": YieldFrom { + "kind": "yieldfrom", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "yield from from();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + "value": Call { + "arguments": [], + "kind": "call", + "loc": Location { + "end": Position { + "column": 17, + "line": 1, + "offset": 17, + }, + "source": "from()", + "start": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + }, + "what": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 15, + "line": 1, + "offset": 15, + }, + "source": "from", + "start": Position { + "column": 11, + "line": 1, + "offset": 11, + }, + }, + "name": "from", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "yield from from();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 18, + "line": 1, + "offset": 18, + }, + "source": "yield from from();", + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; diff --git a/test/snapshot/__snapshots__/loop.test.js.snap b/test/snapshot/__snapshots__/loop.test.js.snap new file mode 100644 index 000000000..459835953 --- /dev/null +++ b/test/snapshot/__snapshots__/loop.test.js.snap @@ -0,0 +1,734 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test loops statements (for, while) fix #122 1`] = ` +Program { + "children": [ + Foreach { + "body": ExpressionStatement { + "expression": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + ], + "kind": "array", + "shortForm": false, + }, + "kind": "expressionstatement", + }, + "key": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "value": undefined, + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""$k -> $v +"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "k", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " -> ", + "unicode": false, + "value": " -> ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "v", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " +", + "unicode": false, + "value": "", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": "VARIABLE", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected 'array' (T_ARRAY) on line 2", + "token": "'array' (T_ARRAY)", + }, + Error { + "expected": ")", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected 'array' (T_ARRAY), expecting ')' on line 2", + "token": "'array' (T_ARRAY)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected ')', expecting ';' on line 2", + "token": "')'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected ')' on line 2", + "token": "')'", + }, + Error { + "expected": ";", + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected 'echo' (T_ECHO), expecting ';' on line 3", + "token": "'echo' (T_ECHO)", + }, + ], + "kind": "program", +} +`; + +exports[`Test loops statements (for, while) fix #122 2`] = ` +Program { + "children": [ + Foreach { + "body": Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""$k -> $v +"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "k", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " -> ", + "unicode": false, + "value": " -> ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "v", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " +", + "unicode": false, + "value": "", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + "key": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + ], + "kind": "list", + "shortForm": true, + }, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + ], + "errors": [ + Error { + "expected": undefined, + "kind": "error", + "line": 2, + "message": "Fatal Error : Cannot use list as key element on line 2", + "token": undefined, + }, + ], + "kind": "program", +} +`; + +exports[`Test loops statements (for, while) test do 1`] = ` +Program { + "children": [ + Do { + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""something"", + "unicode": false, + "value": "something", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "kind": "do", + "test": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test loops statements (for, while) test for 1`] = ` +Program { + "children": [ + For { + "body": Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "i", + }, + ], + "kind": "echo", + "shortForm": false, + }, + "increment": [ + Post { + "kind": "post", + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "i", + }, + }, + ], + "init": [ + Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "i", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "0", + }, + }, + Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "0", + }, + }, + ], + "kind": "for", + "shortForm": false, + "test": [ + Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "i", + }, + "right": Number { + "kind": "number", + "value": "10", + }, + "type": "<", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "ok", + }, + ], + }, + For { + "body": Block { + "children": [ + Echo { + "expressions": [ + Variable { + "curly": false, + "kind": "variable", + "name": "ok", + }, + ], + "kind": "echo", + "shortForm": false, + }, + Continue { + "kind": "continue", + "level": Number { + "kind": "number", + "value": "5", + }, + }, + Continue { + "kind": "continue", + "level": Number { + "kind": "number", + "parenthesizedExpression": true, + "value": "5", + }, + }, + ], + "kind": "block", + }, + "increment": [], + "init": [], + "kind": "for", + "shortForm": true, + "test": [], + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test loops statements (for, while) test foreach 1`] = ` +Program { + "children": [ + Foreach { + "body": Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""$k -> $v +"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "k", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " -> ", + "unicode": false, + "value": " -> ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "v", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " +", + "unicode": false, + "value": "", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + "key": null, + "kind": "foreach", + "shortForm": false, + "source": Variable { + "byref": true, + "curly": false, + "kind": "variable", + "name": "foo", + }, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "v", + }, + }, + Foreach { + "body": Block { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""$a -> $b +"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " -> ", + "unicode": false, + "value": " -> ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " +", + "unicode": false, + "value": "", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "key": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "kind": "foreach", + "shortForm": true, + "source": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "2", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "3", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "4", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + "value": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "c", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "d", + }, + }, + ], + "kind": "list", + "shortForm": true, + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test loops statements (for, while) test while test default form 1`] = ` +Program { + "children": [ + While { + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""go"", + "unicode": false, + "value": "go", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "kind": "while", + "shortForm": false, + "test": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test loops statements (for, while) test while test short form 1`] = ` +Program { + "children": [ + While { + "body": Block { + "children": [ + Echo { + "expressions": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""short"", + "unicode": false, + "value": "short", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "kind": "block", + }, + "kind": "while", + "shortForm": true, + "test": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/magic.test.js.snap b/test/snapshot/__snapshots__/magic.test.js.snap new file mode 100644 index 000000000..696ee8e30 --- /dev/null +++ b/test/snapshot/__snapshots__/magic.test.js.snap @@ -0,0 +1,154 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`magic __CLASS__ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "raw": "__CLASS__", + "value": "__CLASS__", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`magic __DIR__ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "raw": "__DIR__", + "value": "__DIR__", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`magic __FILE__ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "raw": "__FILE__", + "value": "__FILE__", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`magic __FUNCTION__ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "raw": "__FUNCTION__", + "value": "__FUNCTION__", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`magic __LINE__ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "raw": "__LINE__", + "value": "__LINE__", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`magic __LINE__ lowercase 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "raw": "__line__", + "value": "__LINE__", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`magic __METHOD__ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "raw": "__METHOD__", + "value": "__METHOD__", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`magic __NAMESPACE__ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "raw": "__NAMESPACE__", + "value": "__NAMESPACE__", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`magic __TRAIT__ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Magic { + "kind": "magic", + "raw": "__TRAIT__", + "value": "__TRAIT__", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/match.test.js.snap b/test/snapshot/__snapshots__/match.test.js.snap new file mode 100644 index 000000000..42ef068a5 --- /dev/null +++ b/test/snapshot/__snapshots__/match.test.js.snap @@ -0,0 +1,455 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`match can be nested 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "v", + }, + "operator": "=", + "right": Match { + "arms": [ + MatchArm { + "body": Match { + "arms": [ + MatchArm { + "body": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'Connect'", + "unicode": false, + "value": "Connect", + }, + "conds": [ + Number { + "kind": "number", + "value": "1", + }, + ], + "kind": "matcharm", + }, + MatchArm { + "body": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'Auth'", + "unicode": false, + "value": "Auth", + }, + "conds": [ + Number { + "kind": "number", + "value": "2", + }, + ], + "kind": "matcharm", + }, + ], + "cond": Variable { + "curly": false, + "kind": "variable", + "name": "err", + }, + "kind": "match", + }, + "conds": [ + NullKeyword { + "kind": "nullkeyword", + "raw": "null", + }, + ], + "kind": "matcharm", + }, + MatchArm { + "body": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'Ok'", + "unicode": false, + "value": "Ok", + }, + "conds": [ + Match { + "arms": [ + MatchArm { + "body": Number { + "kind": "number", + "value": "0", + }, + "conds": [ + Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + ], + "kind": "matcharm", + }, + MatchArm { + "body": Unary { + "kind": "unary", + "type": "-", + "what": Number { + "kind": "number", + "value": "1", + }, + }, + "conds": [ + Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + ], + "kind": "matcharm", + }, + ], + "cond": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "kind": "match", + }, + ], + "kind": "matcharm", + }, + ], + "cond": Call { + "arguments": [ + Number { + "kind": "number", + "value": "1", + }, + Number { + "kind": "number", + "value": "2", + }, + Number { + "kind": "number", + "value": "3", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "callMe", + "resolution": "uqn", + }, + }, + "kind": "match", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`match can be parsed 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Match { + "arms": [ + MatchArm { + "body": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'yes'", + "unicode": false, + "value": "yes", + }, + "conds": [ + Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + ], + "kind": "matcharm", + }, + MatchArm { + "body": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'no'", + "unicode": false, + "value": "no", + }, + "conds": [ + Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + ], + "kind": "matcharm", + }, + MatchArm { + "body": NullKeyword { + "kind": "nullkeyword", + "raw": "null", + }, + "conds": null, + "kind": "matcharm", + }, + ], + "cond": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "kind": "match", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`match can have hanging comma 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Match { + "arms": [ + MatchArm { + "body": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'ok'", + "unicode": false, + "value": "ok", + }, + "conds": [ + Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + ], + "kind": "matcharm", + }, + MatchArm { + "body": Throw { + "kind": "throw", + "what": New { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'Nope'", + "unicode": false, + "value": "Nope", + }, + ], + "kind": "new", + "what": Name { + "kind": "name", + "name": "Exception", + "resolution": "uqn", + }, + }, + }, + "conds": [ + Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + ], + "kind": "matcharm", + }, + ], + "cond": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "kind": "match", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`match can have lhs, functions 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Match { + "arms": [ + MatchArm { + "body": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'yes'", + "unicode": false, + "value": "yes", + }, + "conds": [ + Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "test", + "resolution": "uqn", + }, + }, + Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "abc", + "resolution": "uqn", + }, + }, + ], + "kind": "matcharm", + }, + MatchArm { + "body": NullKeyword { + "kind": "nullkeyword", + "raw": "null", + }, + "conds": null, + "kind": "matcharm", + }, + ], + "cond": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + "kind": "match", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`match can have multiple values 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "operator": "=", + "right": Match { + "arms": [ + MatchArm { + "body": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "run", + "resolution": "uqn", + }, + }, + "conds": [ + Number { + "kind": "number", + "value": "0", + }, + Number { + "kind": "number", + "value": "1", + }, + Number { + "kind": "number", + "value": "2", + }, + Number { + "kind": "number", + "value": "3", + }, + ], + "kind": "matcharm", + }, + MatchArm { + "body": NullKeyword { + "kind": "nullkeyword", + "raw": "null", + }, + "conds": null, + "kind": "matcharm", + }, + ], + "cond": Name { + "kind": "name", + "name": "trye", + "resolution": "uqn", + }, + "kind": "match", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/namespace.test.js.snap b/test/snapshot/__snapshots__/namespace.test.js.snap new file mode 100644 index 000000000..c59e4055c --- /dev/null +++ b/test/snapshot/__snapshots__/namespace.test.js.snap @@ -0,0 +1,1637 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test namespace statements allow trailing comma for grouped namespaces #177 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "Foo", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "Bar", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "Baz", + "type": null, + }, + ], + "kind": "usegroup", + "name": "Foo\\Bar", + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test namespace statements check silent mode 1`] = ` +Program { + "children": [ + Namespace { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "namespace", + "name": Name { + "kind": "name", + "name": "", + "resolution": "fqn", + }, + "withBrackets": false, + }, + ], + "errors": [ + Error { + "expected": 105, + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected '$var' (T_VARIABLE), expecting T_STRING on line 2", + "token": "'$var' (T_VARIABLE)", + }, + Error { + "expected": [ + "{", + ";", + ], + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected '$var' (T_VARIABLE) on line 2", + "token": "'$var' (T_VARIABLE)", + }, + ], + "kind": "program", +} +`; + +exports[`Test namespace statements fix #246 - doesn't work properly for \`FULL_QUALIFIED_NAME\` 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + "operator": "=", + "right": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "\\Foo", + "resolution": "fqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test namespace statements read usegroup location correctly with docs 1`] = ` +Program { + "children": [ + Namespace { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "loc": Location { + "end": Position { + "column": 25, + "line": 4, + "offset": 59, + }, + "source": null, + "start": Position { + "column": 10, + "line": 4, + "offset": 44, + }, + }, + "name": "Some\\other\\test", + "type": null, + }, + ], + "kind": "usegroup", + "loc": Location { + "end": Position { + "column": 25, + "line": 4, + "offset": 59, + }, + "source": null, + "start": Position { + "column": 6, + "line": 4, + "offset": 40, + }, + }, + "name": null, + "type": null, + }, + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "loc": Location { + "end": Position { + "column": 20, + "line": 10, + "offset": 189, + }, + "source": null, + "start": Position { + "column": 15, + "line": 10, + "offset": 184, + }, + }, + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "loc": Location { + "end": Position { + "column": 20, + "line": 10, + "offset": 189, + }, + "source": null, + "start": Position { + "column": 15, + "line": 10, + "offset": 184, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 20, + "line": 10, + "offset": 189, + }, + "source": null, + "start": Position { + "column": 15, + "line": 10, + "offset": 184, + }, + }, + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "public", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 21, + "line": 13, + "offset": 239, + }, + "source": null, + "start": Position { + "column": 17, + "line": 13, + "offset": 235, + }, + }, + "raw": "true", + "value": true, + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 22, + "line": 13, + "offset": 240, + }, + "source": null, + "start": Position { + "column": 10, + "line": 13, + "offset": 228, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 9, + "line": 14, + "offset": 250, + }, + "source": null, + "start": Position { + "column": 24, + "line": 12, + "offset": 216, + }, + }, + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 9, + "line": 14, + "offset": 250, + }, + "source": null, + "start": Position { + "column": 8, + "line": 12, + "offset": 200, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 21, + "line": 12, + "offset": 213, + }, + "source": null, + "start": Position { + "column": 17, + "line": 12, + "offset": 209, + }, + }, + "name": "test", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 17, + "offset": 313, + }, + "source": null, + "start": Position { + "column": 10, + "line": 17, + "offset": 311, + }, + }, + "name": "a", + }, + "loc": Location { + "end": Position { + "column": 17, + "line": 17, + "offset": 318, + }, + "source": null, + "start": Position { + "column": 10, + "line": 17, + "offset": 311, + }, + }, + "operator": "=", + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 16, + "line": 17, + "offset": 317, + }, + "source": null, + "start": Position { + "column": 15, + "line": 17, + "offset": 316, + }, + }, + "value": "1", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 17, + "line": 17, + "offset": 318, + }, + "source": null, + "start": Position { + "column": 10, + "line": 17, + "offset": 311, + }, + }, + }, + Return { + "expr": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 18, + "offset": 338, + }, + "source": null, + "start": Position { + "column": 17, + "line": 18, + "offset": 336, + }, + }, + "name": "a", + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 20, + "line": 18, + "offset": 339, + }, + "source": null, + "start": Position { + "column": 10, + "line": 18, + "offset": 329, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 9, + "line": 19, + "offset": 349, + }, + "source": null, + "start": Position { + "column": 47, + "line": 16, + "offset": 299, + }, + }, + }, + "byref": true, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 9, + "line": 19, + "offset": 349, + }, + "source": null, + "start": Position { + "column": 8, + "line": 16, + "offset": 260, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 44, + "line": 16, + "offset": 296, + }, + "source": null, + "start": Position { + "column": 25, + "line": 16, + "offset": 277, + }, + }, + "name": "passByReferenceTest", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 27, + "line": 9, + "offset": 145, + }, + "source": null, + "start": Position { + "column": 24, + "line": 9, + "offset": 142, + }, + }, + "name": "Bar", + "resolution": "uqn", + }, + "implements": [ + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 42, + "line": 9, + "offset": 160, + }, + "source": null, + "start": Position { + "column": 39, + "line": 9, + "offset": 157, + }, + }, + "name": "Baz", + "resolution": "uqn", + }, + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 48, + "line": 9, + "offset": 166, + }, + "source": null, + "start": Position { + "column": 44, + "line": 9, + "offset": 162, + }, + }, + "name": "Buzz", + "resolution": "uqn", + }, + ], + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "leadingComments": [ + CommentBlock { + "kind": "commentblock", + "loc": Location { + "end": Position { + "column": 9, + "line": 8, + "offset": 117, + }, + "source": null, + "start": Position { + "column": 6, + "line": 6, + "offset": 68, + }, + }, + "offset": 68, + "value": "/** + * @property \\Test\\test $test + */", + }, + ], + "loc": Location { + "end": Position { + "column": 7, + "line": 20, + "offset": 357, + }, + "source": null, + "start": Position { + "column": 6, + "line": 9, + "offset": 124, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 15, + "line": 9, + "offset": 133, + }, + "source": null, + "start": Position { + "column": 12, + "line": 9, + "offset": 130, + }, + }, + "name": "Foo", + }, + }, + ], + "kind": "namespace", + "loc": Location { + "end": Position { + "column": 7, + "line": 20, + "offset": 357, + }, + "source": null, + "start": Position { + "column": 6, + "line": 2, + "offset": 7, + }, + }, + "name": "Test\\test\\test", + "withBrackets": false, + }, + ], + "comments": [ + CommentBlock { + "kind": "commentblock", + "loc": Location { + "end": Position { + "column": 9, + "line": 8, + "offset": 117, + }, + "source": null, + "start": Position { + "column": 6, + "line": 6, + "offset": 68, + }, + }, + "offset": 68, + "value": "/** + * @property \\Test\\test $test + */", + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 4, + "line": 21, + "offset": 362, + }, + "source": null, + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test namespace statements read usegroup location correctly without docs 1`] = ` +Program { + "children": [ + Namespace { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "loc": Location { + "end": Position { + "column": 25, + "line": 4, + "offset": 59, + }, + "source": null, + "start": Position { + "column": 10, + "line": 4, + "offset": 44, + }, + }, + "name": "Some\\other\\test", + "type": null, + }, + ], + "kind": "usegroup", + "loc": Location { + "end": Position { + "column": 25, + "line": 4, + "offset": 59, + }, + "source": null, + "start": Position { + "column": 6, + "line": 4, + "offset": 40, + }, + }, + "name": null, + "type": null, + }, + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "loc": Location { + "end": Position { + "column": 20, + "line": 10, + "offset": 189, + }, + "source": null, + "start": Position { + "column": 15, + "line": 10, + "offset": 184, + }, + }, + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "loc": Location { + "end": Position { + "column": 20, + "line": 10, + "offset": 189, + }, + "source": null, + "start": Position { + "column": 15, + "line": 10, + "offset": 184, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 20, + "line": 10, + "offset": 189, + }, + "source": null, + "start": Position { + "column": 15, + "line": 10, + "offset": 184, + }, + }, + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "public", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Return { + "expr": Boolean { + "kind": "boolean", + "loc": Location { + "end": Position { + "column": 21, + "line": 13, + "offset": 239, + }, + "source": null, + "start": Position { + "column": 17, + "line": 13, + "offset": 235, + }, + }, + "raw": "true", + "value": true, + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 22, + "line": 13, + "offset": 240, + }, + "source": null, + "start": Position { + "column": 10, + "line": 13, + "offset": 228, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 9, + "line": 14, + "offset": 250, + }, + "source": null, + "start": Position { + "column": 24, + "line": 12, + "offset": 216, + }, + }, + }, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 9, + "line": 14, + "offset": 250, + }, + "source": null, + "start": Position { + "column": 8, + "line": 12, + "offset": 200, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 21, + "line": 12, + "offset": 213, + }, + "source": null, + "start": Position { + "column": 17, + "line": 12, + "offset": 209, + }, + }, + "name": "test", + }, + "nullable": false, + "type": null, + "visibility": "", + }, + Method { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 12, + "line": 17, + "offset": 313, + }, + "source": null, + "start": Position { + "column": 10, + "line": 17, + "offset": 311, + }, + }, + "name": "a", + }, + "loc": Location { + "end": Position { + "column": 17, + "line": 17, + "offset": 318, + }, + "source": null, + "start": Position { + "column": 10, + "line": 17, + "offset": 311, + }, + }, + "operator": "=", + "right": Number { + "kind": "number", + "loc": Location { + "end": Position { + "column": 16, + "line": 17, + "offset": 317, + }, + "source": null, + "start": Position { + "column": 15, + "line": 17, + "offset": 316, + }, + }, + "value": "1", + }, + }, + "kind": "expressionstatement", + "loc": Location { + "end": Position { + "column": 17, + "line": 17, + "offset": 318, + }, + "source": null, + "start": Position { + "column": 10, + "line": 17, + "offset": 311, + }, + }, + }, + Return { + "expr": Variable { + "curly": false, + "kind": "variable", + "loc": Location { + "end": Position { + "column": 19, + "line": 18, + "offset": 338, + }, + "source": null, + "start": Position { + "column": 17, + "line": 18, + "offset": 336, + }, + }, + "name": "a", + }, + "kind": "return", + "loc": Location { + "end": Position { + "column": 20, + "line": 18, + "offset": 339, + }, + "source": null, + "start": Position { + "column": 10, + "line": 18, + "offset": 329, + }, + }, + }, + ], + "kind": "block", + "loc": Location { + "end": Position { + "column": 9, + "line": 19, + "offset": 349, + }, + "source": null, + "start": Position { + "column": 47, + "line": 16, + "offset": 299, + }, + }, + }, + "byref": true, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "loc": Location { + "end": Position { + "column": 9, + "line": 19, + "offset": 349, + }, + "source": null, + "start": Position { + "column": 8, + "line": 16, + "offset": 260, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 44, + "line": 16, + "offset": 296, + }, + "source": null, + "start": Position { + "column": 25, + "line": 16, + "offset": 277, + }, + }, + "name": "passByReferenceTest", + }, + "nullable": false, + "type": null, + "visibility": "public", + }, + ], + "extends": Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 27, + "line": 9, + "offset": 145, + }, + "source": null, + "start": Position { + "column": 24, + "line": 9, + "offset": 142, + }, + }, + "name": "Bar", + "resolution": "uqn", + }, + "implements": [ + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 42, + "line": 9, + "offset": 160, + }, + "source": null, + "start": Position { + "column": 39, + "line": 9, + "offset": 157, + }, + }, + "name": "Baz", + "resolution": "uqn", + }, + Name { + "kind": "name", + "loc": Location { + "end": Position { + "column": 48, + "line": 9, + "offset": 166, + }, + "source": null, + "start": Position { + "column": 44, + "line": 9, + "offset": 162, + }, + }, + "name": "Buzz", + "resolution": "uqn", + }, + ], + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "loc": Location { + "end": Position { + "column": 7, + "line": 20, + "offset": 357, + }, + "source": null, + "start": Position { + "column": 6, + "line": 9, + "offset": 124, + }, + }, + "name": Identifier { + "kind": "identifier", + "loc": Location { + "end": Position { + "column": 15, + "line": 9, + "offset": 133, + }, + "source": null, + "start": Position { + "column": 12, + "line": 9, + "offset": 130, + }, + }, + "name": "Foo", + }, + }, + ], + "kind": "namespace", + "loc": Location { + "end": Position { + "column": 7, + "line": 20, + "offset": 357, + }, + "source": null, + "start": Position { + "column": 6, + "line": 2, + "offset": 7, + }, + }, + "name": "Test\\test\\test", + "withBrackets": false, + }, + ], + "errors": [], + "kind": "program", + "loc": Location { + "end": Position { + "column": 4, + "line": 21, + "offset": 362, + }, + "source": null, + "start": Position { + "column": 0, + "line": 1, + "offset": 0, + }, + }, +} +`; + +exports[`Test namespace statements test bare namespace separator 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Error { + "expected": "SCALAR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '\\' (T_NS_SEPARATOR) on line 1", + "token": "'\\' (T_NS_SEPARATOR)", + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "SCALAR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '\\' (T_NS_SEPARATOR) on line 1", + "token": "'\\' (T_NS_SEPARATOR)", + }, + ], + "kind": "program", +} +`; + +exports[`Test namespace statements test keywords 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "enum", + "resolution": "rn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "\\foo\\trait\\class", + "resolution": "fqn", + }, + }, + "kind": "expressionstatement", + }, + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "a", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "b", + "type": null, + }, + ], + "kind": "usegroup", + "name": "\\foo\\bar", + "type": null, + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Name { + "kind": "name", + "name": "bar", + "resolution": "rn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test namespace statements test multiple namespace 1`] = ` +Program { + "children": [ + Namespace { + "children": [ + ExpressionStatement { + "expression": Post { + "kind": "post", + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "i", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "namespace", + "name": "\\foo", + "withBrackets": true, + }, + Namespace { + "children": [ + ExpressionStatement { + "expression": Post { + "kind": "post", + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "namespace", + "name": [ + "", + ], + "withBrackets": true, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test namespace statements test namespace error 1`] = ` +Program { + "children": [ + Namespace { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "namespace", + "name": Name { + "kind": "name", + "name": "", + "resolution": "fqn", + }, + "withBrackets": false, + }, + ], + "errors": [ + Error { + "expected": 105, + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected '$var' (T_VARIABLE), expecting T_STRING on line 2", + "token": "'$var' (T_VARIABLE)", + }, + Error { + "expected": [ + "{", + ";", + ], + "kind": "error", + "line": 2, + "message": "Parse Error : syntax error, unexpected '$var' (T_VARIABLE) on line 2", + "token": "'$var' (T_VARIABLE)", + }, + ], + "kind": "program", +} +`; + +exports[`Test namespace statements test namespace keyword 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "rn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Name { + "kind": "name", + "name": "bar", + "resolution": "rn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test namespace statements test single namespace 1`] = ` +Program { + "children": [ + Namespace { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "barBaz", + }, + "kind": "useitem", + "name": "bar\\baz", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": null, + }, + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "barBaz", + }, + "kind": "useitem", + "name": "bar\\baz", + "type": null, + }, + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "bazBoo", + }, + "kind": "useitem", + "name": "baz\\boo", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": "const", + }, + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "barBaz", + }, + "kind": "useitem", + "name": "bar\\baz", + "type": null, + }, + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "bazBoo", + }, + "kind": "useitem", + "name": "baz\\boo", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": "function", + }, + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "BAZ_FOO", + }, + "kind": "useitem", + "name": "FOO", + "type": "const", + }, + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "BAZ_BOO", + }, + "kind": "useitem", + "name": "BOO", + "type": "function", + }, + ], + "kind": "usegroup", + "name": "bar\\baz", + "type": null, + }, + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "AZERTY_A", + }, + "kind": "useitem", + "name": "A", + "type": null, + }, + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "AZERTY_B", + }, + "kind": "useitem", + "name": "B", + "type": null, + }, + ], + "kind": "usegroup", + "name": "azerty", + "type": "const", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Name { + "kind": "name", + "name": "barBaz", + "resolution": "rn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "operator": "=", + "right": Name { + "kind": "name", + "name": "\\barBaz", + "resolution": "fqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "c", + }, + "operator": "=", + "right": Name { + "kind": "name", + "name": "barBaz\\foo", + "resolution": "qn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "d", + }, + "operator": "=", + "right": Name { + "kind": "name", + "name": "barBaz", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "namespace", + "name": "foo", + "withBrackets": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test namespace statements work with declare statement 1`] = ` +Program { + "children": [ + Declare { + "children": [], + "directives": [ + DeclareDirective { + "key": Identifier { + "kind": "identifier", + "name": "strict_types", + }, + "kind": "declaredirective", + "value": Number { + "kind": "number", + "value": "1", + }, + }, + ], + "kind": "declare", + "mode": "none", + }, + Namespace { + "children": [ + Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "bar", + }, + }, + ], + "kind": "namespace", + "name": "foo", + "withBrackets": false, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/new.test.js.snap b/test/snapshot/__snapshots__/new.test.js.snap new file mode 100644 index 000000000..58d7c35f8 --- /dev/null +++ b/test/snapshot/__snapshots__/new.test.js.snap @@ -0,0 +1,715 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`new #348 - byref usage deprecated 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": undefined, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'new' (T_NEW) on line 1", + "token": "'new' (T_NEW)", + }, + ], + "kind": "program", +} +`; + +exports[`new anonymous 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": null, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new anonymous class #2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": New { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + "kind": "new", + "what": Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": null, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new anonymous class #3 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": New { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + "kind": "new", + "what": Class { + "attrGroups": [], + "body": [], + "extends": Name { + "kind": "name", + "name": "SomeClass", + "resolution": "uqn", + }, + "implements": [ + Name { + "kind": "name", + "name": "SomeInterface", + "resolution": "uqn", + }, + ], + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": null, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new anonymous class 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": New { + "arguments": [], + "kind": "new", + "what": Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": null, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new anonymous no parens 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": null, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new anonymous with argument 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + "kind": "new", + "what": Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": null, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new anonymous with multiple argument 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "one", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "two", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "three", + }, + ], + "kind": "new", + "what": Class { + "attrGroups": [], + "body": [], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": true, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": null, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new no parens 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new parent 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new result from function 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": New { + "arguments": [], + "kind": "new", + "what": Call { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'d'", + "unicode": false, + "value": "d", + }, + ], + "kind": "call", + "what": Call { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'c'", + "unicode": false, + "value": "c", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "b", + "resolution": "uqn", + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new result from function with arguments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": New { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'e'", + "unicode": false, + "value": "e", + }, + ], + "kind": "new", + "what": Call { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'d'", + "unicode": false, + "value": "d", + }, + ], + "kind": "call", + "what": Call { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'c'", + "unicode": false, + "value": "c", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "b", + "resolution": "uqn", + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new self 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new simple (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "\\Foo", + "resolution": "fqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new simple (3) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "Foo\\Foo", + "resolution": "qn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new simple (4) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "\\Foo\\Foo", + "resolution": "fqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new static 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": StaticReference { + "kind": "staticreference", + "raw": "static", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new static array 1`] = ` +Program { + "children": [ + Return { + "expr": New { + "arguments": [], + "kind": "new", + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "map", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "mapping", + }, + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + }, + }, + "kind": "return", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new trailing comma 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""constructor"", + "unicode": false, + "value": "constructor", + }, + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + ], + "kind": "new", + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [], + "kind": "new", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`new with arguments 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": New { + "arguments": [ + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""constructor"", + "unicode": false, + "value": "constructor", + }, + String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + ], + "kind": "new", + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/nowdoc.test.js.snap b/test/snapshot/__snapshots__/nowdoc.test.js.snap new file mode 100644 index 000000000..73ee4fa13 --- /dev/null +++ b/test/snapshot/__snapshots__/nowdoc.test.js.snap @@ -0,0 +1,473 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`nowdoc Flexible nowdoc syntax: 4 spaces of indentation 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Nowdoc { + "kind": "nowdoc", + "label": "END", + "raw": "<<<'END' + a + b + c + END", + "value": " a + b +c", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc Flexible nowdoc syntax: with variables 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Nowdoc { + "kind": "nowdoc", + "label": "END", + "raw": "<<<'END' + a + {$foo->bar[1]} + b + c + END", + "value": " a + {$foo->bar[1]} + b +c", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc Followed by string interpolation 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "x", + }, + "operator": "=", + "right": Nowdoc { + "kind": "nowdoc", + "label": "NOWDOC", + "raw": "<<<'NOWDOC' + ... + NOWDOC", + "value": "...", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "y", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""_$z"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "_", + "unicode": false, + "value": "_", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "z", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc empty 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Nowdoc { + "kind": "nowdoc", + "label": "TEST", + "raw": "<<<'TEST' +TEST", + "value": "", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc inside call 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [ + Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Nowdoc { + "kind": "nowdoc", + "label": "EOD", + "raw": "<<<'EOD' +foobar! +EOD +", + "value": "foobar!", + }, + }, + ], + "kind": "array", + "shortForm": false, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "var_dump", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc inside class 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + ClassConstant { + "attrGroups": [], + "constants": [ + Constant { + "kind": "constant", + "name": Identifier { + "kind": "identifier", + "name": "BAR", + }, + "value": Nowdoc { + "kind": "nowdoc", + "label": "FOOBAR", + "raw": "<<<'FOOBAR' +Constant example +FOOBAR", + "value": "Constant example", + }, + }, + ], + "final": false, + "kind": "classconstant", + "nullable": false, + "type": null, + "visibility": "", + }, + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "baz", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Nowdoc { + "kind": "nowdoc", + "label": "FOOBAR", + "raw": "<<<'FOOBAR' +Property example +FOOBAR", + "value": "Property example", + }, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc inside function 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + Static { + "kind": "static", + "variables": [ + StaticVariable { + "defaultValue": Nowdoc { + "kind": "nowdoc", + "label": "LABEL", + "raw": "<<<'LABEL' +Nothing in here... +LABEL", + "value": "Nothing in here...", + }, + "kind": "staticvariable", + "variable": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + ], + }, + ], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc only newline 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Nowdoc { + "kind": "nowdoc", + "label": "TEST", + "raw": "<<<'TEST' + +TEST", + "value": "", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc simple 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Nowdoc { + "kind": "nowdoc", + "label": "EOD", + "raw": "<<<'EOD' +Example of string +spanning multiple lines +using heredoc syntax. +EOD", + "value": "Example of string +spanning multiple lines +using heredoc syntax.", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc space between <<< and label 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Nowdoc { + "kind": "nowdoc", + "label": "TEST", + "raw": "<<< 'TEST' + a + b +c +TEST", + "value": " a + b +c", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc tab between <<< and label 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Nowdoc { + "kind": "nowdoc", + "label": "TEST", + "raw": "<<< 'TEST' + a + b +c +TEST", + "value": " a + b +c", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc with space between <<< and label 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Nowdoc { + "kind": "nowdoc", + "label": "EOD", + "raw": "<<< 'EOD' +Example of string +spanning multiple lines +using heredoc syntax. +EOD", + "value": "Example of string +spanning multiple lines +using heredoc syntax.", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nowdoc with variables 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Nowdoc { + "kind": "nowdoc", + "label": "EOT", + "raw": "<<<'EOT' +My name is "$name". I am printing some $foo->foo. +Now, I am printing some {$foo->bar[1]}. +This should print a capital 'A': A +EOT", + "value": "My name is "$name". I am printing some $foo->foo. +Now, I am printing some {$foo->bar[1]}. +This should print a capital 'A': A", + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/nullsavepropertylookup.test.js.snap b/test/snapshot/__snapshots__/nullsavepropertylookup.test.js.snap new file mode 100644 index 000000000..76bb3a145 --- /dev/null +++ b/test/snapshot/__snapshots__/nullsavepropertylookup.test.js.snap @@ -0,0 +1,109 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`nullsavepropertylookup call 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nullsavepropertylookup multiple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property_2", + }, + "what": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property_1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nullsavepropertylookup simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "property", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`nullsavepropertylookup variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": NullSafePropertyLookup { + "kind": "nullsafepropertylookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/number.test.js.snap b/test/snapshot/__snapshots__/number.test.js.snap new file mode 100644 index 000000000..608a99aad --- /dev/null +++ b/test/snapshot/__snapshots__/number.test.js.snap @@ -0,0 +1,684 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test numbers binary with 2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "0", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'b2' (T_STRING), expecting ';' on line 1", + "token": "'b2' (T_STRING)", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test numbers exponent empty 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "7", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'EX' (T_STRING), expecting ';' on line 1", + "token": "'EX' (T_STRING)", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test numbers exponent with letter 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "d", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "7", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Name { + "kind": "name", + "name": "E", + "resolution": "uqn", + }, + "right": Name { + "kind": "name", + "name": "a", + "resolution": "uqn", + }, + "type": "-", + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'E' (T_STRING), expecting ';' on line 1", + "token": "'E' (T_STRING)", + }, + ], + "kind": "program", +} +`; + +exports[`Test numbers hexa without hex 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "0", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'xx' (T_STRING), expecting ';' on line 1", + "token": "'xx' (T_STRING)", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test numbers multiple points 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1.0", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Number { + "kind": "number", + "value": ".5", + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '.5' (T_DNUMBER), expecting ';' on line 1", + "token": "'.5' (T_DNUMBER)", + }, + ], + "kind": "program", +} +`; + +exports[`Test numbers test common cases 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Number { + "kind": "number", + "value": "1234", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Unary { + "kind": "unary", + "type": "-", + "what": Number { + "kind": "number", + "value": "1.5", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1234", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "c", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "9223372036854775807", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "c", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "9223372036854775808", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "d", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "0x1A", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "d", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "0xFF", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "0b1011", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "f", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "0123", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "g", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "1.2e3", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "h", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "7E-10", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test numbers underscore #1 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "7", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '__0' (T_STRING), expecting ';' on line 1", + "token": "'__0' (T_STRING)", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test numbers underscore #2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "7.", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '_0' (T_STRING), expecting ';' on line 1", + "token": "'_0' (T_STRING)", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test numbers underscore #3 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "7", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Name { + "kind": "name", + "name": "_", + "resolution": "uqn", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Number { + "kind": "number", + "value": ".0", + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '_' (T_STRING), expecting ';' on line 1", + "token": "'_' (T_STRING)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '.0' (T_DNUMBER), expecting ';' on line 1", + "token": "'.0' (T_DNUMBER)", + }, + ], + "kind": "program", +} +`; + +exports[`Test numbers underscore #4 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "7", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'e_0' (T_STRING), expecting ';' on line 1", + "token": "'e_0' (T_STRING)", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test numbers underscore #5 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "7_", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'e0' (T_STRING), expecting ';' on line 1", + "token": "'e0' (T_STRING)", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test numbers variant (for coverage) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "d", + }, + "operator": "=", + "right": Number { + "kind": "number", + "value": "7", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Bin { + "kind": "bin", + "left": Name { + "kind": "name", + "name": "e", + "resolution": "uqn", + }, + "right": Name { + "kind": "name", + "name": "a", + "resolution": "uqn", + }, + "type": "+", + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'e' (T_STRING), expecting ';' on line 1", + "token": "'e' (T_STRING)", + }, + ], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/offsetlookup.test.js.snap b/test/snapshot/__snapshots__/offsetlookup.test.js.snap new file mode 100644 index 000000000..f2de7e5ed --- /dev/null +++ b/test/snapshot/__snapshots__/offsetlookup.test.js.snap @@ -0,0 +1,535 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`offsetlookup call (curly) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`offsetlookup call 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`offsetlookup inside propertylookup (curly) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bzr_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'string'", + "unicode": false, + "value": "string", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bzr_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "baz", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bzr_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "baz", + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bzr_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": RetIf { + "falseExpr": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'two'", + "unicode": false, + "value": "two", + }, + "kind": "retif", + "test": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "trueExpr": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'one'", + "unicode": false, + "value": "one", + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bzr_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`offsetlookup inside propertylookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bzr_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'string'", + "unicode": false, + "value": "string", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bzr_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "baz", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bzr_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "baz", + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bzr_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": RetIf { + "falseExpr": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'two'", + "unicode": false, + "value": "two", + }, + "kind": "retif", + "test": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "trueExpr": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'one'", + "unicode": false, + "value": "one", + }, + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bzr_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`offsetlookup multiple (curly) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""second"", + "unicode": false, + "value": "second", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""first"", + "unicode": false, + "value": "first", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`offsetlookup multiple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""second"", + "unicode": false, + "value": "second", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""first"", + "unicode": false, + "value": "first", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`offsetlookup simple (curly) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""index"", + "unicode": false, + "value": "index", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`offsetlookup simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""index"", + "unicode": false, + "value": "index", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`offsetlookup variable (curly) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`offsetlookup variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/parentreference.test.js.snap b/test/snapshot/__snapshots__/parentreference.test.js.snap new file mode 100644 index 000000000..ec202a126 --- /dev/null +++ b/test/snapshot/__snapshots__/parentreference.test.js.snap @@ -0,0 +1,278 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`parentreference argument (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": ParentReference { + "kind": "parentreference", + "raw": "PARENT", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`parentreference argument 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`parentreference call 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`parentreference constant 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "CONSTANT", + }, + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`parentreference return type declarations (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": ParentReference { + "kind": "parentreference", + "raw": "PARENT", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`parentreference return type declarations 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`parentreference uppercase 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "call", + }, + "what": ParentReference { + "kind": "parentreference", + "raw": "PARENT", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`parentreference variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/php5.test.js.snap b/test/snapshot/__snapshots__/php5.test.js.snap new file mode 100644 index 000000000..e8fcd25a5 --- /dev/null +++ b/test/snapshot/__snapshots__/php5.test.js.snap @@ -0,0 +1,158 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test syntax parsing without PHP7 support special keywords should fail 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + Method { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": null, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": null, + "byref": false, + "isAbstract": false, + "isFinal": false, + "isReadonly": false, + "isStatic": false, + "kind": "method", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + "visibility": "", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": "IDENTIFIER", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'list' (T_LIST) on line 1", + "token": "'list' (T_LIST)", + }, + Error { + "expected": "(", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'list' (T_LIST), expecting '(' on line 1", + "token": "'list' (T_LIST)", + }, + Error { + "expected": 222, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'list' (T_LIST), expecting T_VARIABLE on line 1", + "token": "'list' (T_LIST)", + }, + Error { + "expected": [ + ",", + ")", + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'list' (T_LIST) on line 1", + "token": "'list' (T_LIST)", + }, + Error { + "expected": ")", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'list' (T_LIST), expecting ')' on line 1", + "token": "'list' (T_LIST)", + }, + Error { + "expected": "{", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'list' (T_LIST), expecting '{' on line 1", + "token": "'list' (T_LIST)", + }, + Error { + "expected": [ + 198, + 222, + 182, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected 'list' (T_LIST) on line 1", + "token": "'list' (T_LIST)", + }, + Error { + "expected": [ + 198, + 222, + 182, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '(' on line 1", + "token": "'('", + }, + Error { + "expected": [ + 198, + 222, + 182, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected ')' on line 1", + "token": "')'", + }, + Error { + "expected": [ + 198, + 222, + 182, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '{' on line 1", + "token": "'{'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '}' on line 1", + "token": "'}'", + }, + ], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/php73.test.js.snap b/test/snapshot/__snapshots__/php73.test.js.snap new file mode 100644 index 000000000..f90e6f427 --- /dev/null +++ b/test/snapshot/__snapshots__/php73.test.js.snap @@ -0,0 +1,571 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test syntax parsing with PHP 73 support https://wiki.php.net/rfc/list_reference_assignment 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + Entry { + "byRef": true, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + ], + "kind": "list", + "shortForm": true, + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + Entry { + "byRef": true, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + ], + "kind": "list", + "shortForm": false, + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "array", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test syntax parsing with PHP 73 support https://wiki.php.net/rfc/trailing-comma-function-calls 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "newArray", + }, + "operator": "=", + "right": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "arrayOne", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "arrayTwo", + }, + Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'foo'", + "unicode": false, + "value": "foo", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'bar'", + "unicode": false, + "value": "bar", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "array_merge", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "operator": "=", + "right": New { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'constructor'", + "unicode": false, + "value": "constructor", + }, + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'bar'", + "unicode": false, + "value": "bar", + }, + ], + "kind": "new", + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'method'", + "unicode": false, + "value": "method", + }, + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'bar'", + "unicode": false, + "value": "bar", + }, + ], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'invoke'", + "unicode": false, + "value": "invoke", + }, + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'bar'", + "unicode": false, + "value": "bar", + }, + ], + "kind": "call", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + "kind": "expressionstatement", + }, + Unset { + "kind": "unset", + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + ], + }, + ExpressionStatement { + "expression": Call { + "arguments": [ + Isset { + "kind": "isset", + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + ], + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "var_dump", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test syntax parsing with PHP 73 support https://wiki.php.net/rfc/trailing-comma-function-calls#errors 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "a", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "b", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": null, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "bar", + }, + "nullable": false, + "type": null, + }, + ExpressionStatement { + "expression": Call { + "arguments": [ + undefined, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'function'", + "unicode": false, + "value": "function", + }, + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'bar'", + "unicode": false, + "value": "bar", + }, + Noop { + "kind": "noop", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [ + undefined, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'function'", + "unicode": false, + "value": "function", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'bar'", + "unicode": false, + "value": "bar", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": 222, + "kind": "error", + "line": 3, + "message": "Parse Error : syntax error, unexpected ')', expecting T_VARIABLE on line 3", + "token": "')'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 7, + "message": "Parse Error : syntax error, unexpected ',' on line 7", + "token": "','", + }, + Error { + "expected": ")", + "kind": "error", + "line": 10, + "message": "Parse Error : syntax error, unexpected ',', expecting ')' on line 10", + "token": "','", + }, + Error { + "expected": ";", + "kind": "error", + "line": 10, + "message": "Parse Error : syntax error, unexpected ',', expecting ';' on line 10", + "token": "','", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 10, + "message": "Parse Error : syntax error, unexpected ',' on line 10", + "token": "','", + }, + Error { + "expected": ";", + "kind": "error", + "line": 10, + "message": "Parse Error : syntax error, unexpected ')', expecting ';' on line 10", + "token": "')'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 10, + "message": "Parse Error : syntax error, unexpected ')' on line 10", + "token": "')'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 12, + "message": "Parse Error : syntax error, unexpected ',' on line 12", + "token": "','", + }, + Error { + "expected": ")", + "kind": "error", + "line": 12, + "message": "Parse Error : syntax error, unexpected ''function'' (T_CONSTANT_ENCAPSED_STRING), expecting ')' on line 12", + "token": "''function'' (T_CONSTANT_ENCAPSED_STRING)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 12, + "message": "Parse Error : syntax error, unexpected ''function'' (T_CONSTANT_ENCAPSED_STRING), expecting ';' on line 12", + "token": "''function'' (T_CONSTANT_ENCAPSED_STRING)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 12, + "message": "Parse Error : syntax error, unexpected ',', expecting ';' on line 12", + "token": "','", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 12, + "message": "Parse Error : syntax error, unexpected ',' on line 12", + "token": "','", + }, + Error { + "expected": ";", + "kind": "error", + "line": 12, + "message": "Parse Error : syntax error, unexpected ''bar'' (T_CONSTANT_ENCAPSED_STRING), expecting ';' on line 12", + "token": "''bar'' (T_CONSTANT_ENCAPSED_STRING)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 12, + "message": "Parse Error : syntax error, unexpected ')', expecting ';' on line 12", + "token": "')'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 12, + "message": "Parse Error : syntax error, unexpected ')' on line 12", + "token": "')'", + }, + ], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/post.test.js.snap b/test/snapshot/__snapshots__/post.test.js.snap new file mode 100644 index 000000000..ad233a369 --- /dev/null +++ b/test/snapshot/__snapshots__/post.test.js.snap @@ -0,0 +1,241 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`post ++ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Post { + "kind": "post", + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`post ++ and + unary 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": Post { + "kind": "post", + "parenthesizedExpression": true, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`post ++ and - unary (with parens) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Post { + "kind": "post", + "parenthesizedExpression": true, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`post ++ and - unary 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Post { + "kind": "post", + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`post ++ and parens 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Post { + "kind": "post", + "parenthesizedExpression": true, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`post -- 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Post { + "kind": "post", + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`post -- and + unary (with parens) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": Post { + "kind": "post", + "parenthesizedExpression": true, + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`post -- and + unary 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": Post { + "kind": "post", + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`post -- and parens 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Post { + "kind": "post", + "parenthesizedExpression": true, + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`post -- and unary - 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Post { + "kind": "post", + "parenthesizedExpression": true, + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/pre.test.js.snap b/test/snapshot/__snapshots__/pre.test.js.snap new file mode 100644 index 000000000..aa1a5f8d3 --- /dev/null +++ b/test/snapshot/__snapshots__/pre.test.js.snap @@ -0,0 +1,241 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`pre ++ 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Pre { + "kind": "pre", + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`pre ++ and + unary 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": Pre { + "kind": "pre", + "parenthesizedExpression": true, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`pre ++ and - unary (with parens) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Pre { + "kind": "pre", + "parenthesizedExpression": true, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`pre ++ and - unary 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Pre { + "kind": "pre", + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`pre ++ and parens 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Pre { + "kind": "pre", + "parenthesizedExpression": true, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`pre -- 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Pre { + "kind": "pre", + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`pre -- and + unary (with parens) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": Pre { + "kind": "pre", + "parenthesizedExpression": true, + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`pre -- and + unary 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": Pre { + "kind": "pre", + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`pre -- and parens 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Pre { + "kind": "pre", + "parenthesizedExpression": true, + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`pre -- and unary - 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Pre { + "kind": "pre", + "parenthesizedExpression": true, + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/print.test.js.snap b/test/snapshot/__snapshots__/print.test.js.snap new file mode 100644 index 000000000..3008dfbf8 --- /dev/null +++ b/test/snapshot/__snapshots__/print.test.js.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`print simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Print { + "expression": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""string"", + "unicode": false, + "value": "string", + }, + "kind": "print", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/property.test.js.snap b/test/snapshot/__snapshots__/property.test.js.snap new file mode 100644 index 000000000..59f1edd5f --- /dev/null +++ b/test/snapshot/__snapshots__/property.test.js.snap @@ -0,0 +1,1118 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`property private 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "private", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property private with value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Number { + "kind": "number", + "value": "10", + }, + }, + ], + "visibility": "private", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property protected 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "protected", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property protected with value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Number { + "kind": "number", + "value": "10", + }, + }, + ], + "visibility": "protected", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property public 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property public static 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": true, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property public static with value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": true, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Number { + "kind": "number", + "value": "10", + }, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property public with value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Number { + "kind": "number", + "value": "10", + }, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property var 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + }, + ], + "visibility": null, + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property var with value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Number { + "kind": "number", + "value": "10", + }, + }, + ], + "visibility": null, + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property with array value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Boolean { + "kind": "boolean", + "raw": "false", + "value": false, + }, + }, + ], + "kind": "array", + "shortForm": false, + }, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property with bin value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Bin { + "kind": "bin", + "left": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'hello '", + "unicode": false, + "value": "hello ", + }, + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'world'", + "unicode": false, + "value": "world", + }, + "type": ".", + }, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property with bin value 2 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Bin { + "kind": "bin", + "left": Number { + "kind": "number", + "value": "1", + }, + "right": Number { + "kind": "number", + "value": "2", + }, + "type": "+", + }, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property with boolean value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property with constant value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Name { + "kind": "name", + "name": "CONSTANT", + "resolution": "uqn", + }, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property with double quotes string value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""string"", + "unicode": false, + "value": "string", + }, + }, + ], + "visibility": "public", + }, + ], + "extends": null, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "Foo", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`property with heredoc value 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + PropertyStatement { + "isStatic": false, + "kind": "propertystatement", + "properties": [ + Property { + "attrGroups": [], + "kind": "property", + "name": Identifier { + "kind": "identifier", + "name": "property", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": Encapsed { + "kind": "encapsed", + "label": "EOD", + "raw": "<<$colors[1]<\\\\n\\"", + "type": "string", + "value": Array [ + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "\\\\colors[1] contains >", + "value": "\\\\colors[1] contains >", + }, + OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": Variable { + "byref": false, + "curly": false, + "kind": "variable", + "name": "colors", + }, + }, + String { + "isDoubleQuote": false, + "kind": "string", + "raw": "<\\\\n", + "value": "< +", + }, + ], + }, + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": Array [], + "kind": "program", +} +`; + +exports[`Test strings check infinite on $ using backquotes 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": "\`$", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "$", + "unicode": false, + "value": "$", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": "\`", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '\`' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on $ using doublequotes 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""$", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "$", + "unicode": false, + "value": "$", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": """, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '"' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on $ with arrow 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": "\` -> $", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " -> $", + "unicode": false, + "value": " -> $", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": "\`", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '\`' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on \${ using backquotes 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": "\`\${", + "type": "shell", + "value": [ + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": undefined, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '}' on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": "\`", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '\`' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on \${ using doublequotes 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""\${", + "type": "string", + "value": [ + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": undefined, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '}' on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": """, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '"' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on \${ with arrow 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": "\` -> \${", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " -> ", + "unicode": false, + "value": " -> ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": undefined, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": "EXPR", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '}' on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": "\`", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '\`' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on { using backquotes 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": "\`{", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "{", + "unicode": false, + "value": "{", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": "\`", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '\`' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on { using doublequotes 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""{", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "{", + "unicode": false, + "value": "{", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": """, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '"' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on { with arrow 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": "\` -> {", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " -> {", + "unicode": false, + "value": " -> {", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": "\`", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '\`' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on {$ using backquotes 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": "\`{$", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": [ + "{", + "$", + 222, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '}' on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": "\`", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '\`' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on {$ using doublequotes 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""{$", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": [ + "{", + "$", + 222, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '}' on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": """, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '"' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings check infinite on {$ with arrow 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": "\` -> {$", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " -> ", + "unicode": false, + "value": " -> ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [ + Error { + "expected": [ + "{", + "$", + 222, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '}' on line 1", + "token": "the end of file (EOF)", + }, + Error { + "expected": "\`", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, expecting '\`' on line 1", + "token": "the end of file (EOF)", + }, + ], + "kind": "program", +} +`; + +exports[`Test strings double quotes 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\n"", + "unicode": false, + "value": " +", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\r"", + "unicode": false, + "value": " +", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\t"", + "unicode": false, + "value": " ", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\v"", + "unicode": false, + "value": " ", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\e"", + "unicode": false, + "value": "", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\f"", + "unicode": false, + "value": " ", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\\\"", + "unicode": false, + "value": "\\", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\$"", + "unicode": false, + "value": "$", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\""", + "unicode": false, + "value": """, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\141"", + "unicode": false, + "value": "a", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\7FF"", + "unicode": false, + "value": "FF", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\x61"", + "unicode": false, + "value": "a", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\x0Z"", + "unicode": false, + "value": "Z", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\xZZ"", + "unicode": false, + "value": "\\xZZ", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\u{0061}"", + "unicode": false, + "value": "a", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\u{}"", + "unicode": false, + "value": "\\u{}", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\u{0FFF}"", + "unicode": false, + "value": "࿿", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\u{0ZZZ}"", + "unicode": false, + "value": "\\u{0ZZZ}", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""cat\\u{1F639}"", + "unicode": false, + "value": "cat😹", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\u{D83D}\\u{DCA9}"", + "unicode": false, + "value": "💩", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""💩"", + "unicode": false, + "value": "💩", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\u{ZZZZ}\\u{ZZZZ}"", + "unicode": false, + "value": "\\u{ZZZZ}\\u{ZZZZ}", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""🌟"", + "unicode": false, + "value": "🌟", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""'"", + "unicode": false, + "value": "'", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\'"", + "unicode": false, + "value": "\\'", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\n | \\r | \\t | \\v | \\e | \\f | \\\\ | \\$ | \\" | \\141 | \\x61 | \\u{0061}"", + "unicode": false, + "value": " + | + | | |  | | \\ | $ | " | a | a | a", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings encapsed variable / curly constant 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""Hello \${ obj }"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "Hello ", + "unicode": false, + "value": "Hello ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": Name { + "kind": "name", + "name": "obj", + "resolution": "uqn", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings encapsed variable / curly varname 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""Hello \${obj}->name !"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "Hello ", + "unicode": false, + "value": "Hello ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "->name !", + "unicode": false, + "value": "->name !", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings encapsed variable / offsetlookup 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""\${$parts[$i]}\\n"", + "type": "string", + "value": [ + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "i", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "parts", + }, + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "\\n", + "unicode": false, + "value": "", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings fix #101 case 1 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""encapsed {$var}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "encapsed ", + "unicode": false, + "value": "encapsed ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings fix #101 case 2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""encapsed {$arr[0]}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "encapsed ", + "unicode": false, + "value": "encapsed ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "0", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "arr", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings fix #101 case 3 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""encapsed \${var}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "encapsed ", + "unicode": false, + "value": "encapsed ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings fix #123 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "string", + }, + "operator": "=", + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'Avoid converting + chars, but \\' or \\\\ is ok.'", + "unicode": false, + "value": "Avoid converting + chars, but ' or \\ is ok.", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings fix #124 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "string", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""He drank some $juices[koolaid1] juice."", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "He drank some ", + "unicode": false, + "value": "He drank some ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Identifier { + "kind": "identifier", + "name": "koolaid1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "juices", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " juice.", + "unicode": false, + "value": " juice.", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings fix #144 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Encapsed { + "kind": "encapsed", + "raw": ""encapsed \\" {$var}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "encapsed \\" ", + "unicode": false, + "value": "encapsed " ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings fix #149 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": "b"foo\\nbar"", + "unicode": true, + "value": "foo +bar", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings fix #251 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""string \${juices['FOO']} string"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "string ", + "unicode": false, + "value": "string ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'FOO'", + "unicode": false, + "value": "FOO", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "juices", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " string", + "unicode": false, + "value": " string", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings implement #116 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""foo\\nbar"", + "unicode": false, + "value": "foo +bar", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings single (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""string"", + "unicode": false, + "value": "string", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings single 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'string'", + "unicode": false, + "value": "string", + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings single quotes 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'foo'", + "unicode": false, + "value": "foo", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'\\''", + "unicode": false, + "value": "'", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'\\'\\'\\''", + "unicode": false, + "value": "'''", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'\\'foo'", + "unicode": false, + "value": "'foo", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'foo\\''", + "unicode": false, + "value": "foo'", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'foo\\'foo'", + "unicode": false, + "value": "foo'foo", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'\\\\\\''", + "unicode": false, + "value": "\\'", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings test backquotes 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`ls $cwd\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "ls ", + "unicode": false, + "value": "ls ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "cwd", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`ls \${$cwd}\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "ls ", + "unicode": false, + "value": "ls ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "cwd", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`ls {$cwd}\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "ls ", + "unicode": false, + "value": "ls ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "cwd", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`$var\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`\${var}\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`{$var}\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`\`", + "type": "shell", + "value": [], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`\\\`\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "\\\`", + "unicode": false, + "value": "\\\`", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`{\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "{", + "unicode": false, + "value": "{", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`-{\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "-{", + "unicode": false, + "value": "-{", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`-$\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "-$", + "unicode": false, + "value": "-$", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": "\`$\`", + "type": "shell", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "$", + "unicode": false, + "value": "$", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings test binary with double quotes 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": "b"\\colors contains >$colors<\\n"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "\\colors contains >", + "unicode": false, + "value": "\\colors contains >", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "colors", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "<\\n", + "unicode": false, + "value": "<", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings test double quotes 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""$"", + "unicode": false, + "value": "$", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""{"", + "unicode": false, + "value": "{", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""-$-"", + "unicode": false, + "value": "-$-", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""-{"", + "unicode": false, + "value": "-{", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""$b"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""{$b}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""\${$b}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""-$b?"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "-", + "unicode": false, + "value": "-", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "?", + "unicode": false, + "value": "?", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""-{$b}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "-", + "unicode": false, + "value": "-", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""-\${$b}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "-", + "unicode": false, + "value": "-", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": """", + "unicode": false, + "value": "", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""\\""", + "unicode": false, + "value": """, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings test empty nowdoc & heredoc contents 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "label": "HDOC", + "raw": "<<docStar} +\${$foo} +\${targetDirs[1]} +$test[1] +$test->foo +EOFX", + "type": "heredoc", + "value": [ + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "docStar", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " +", + "unicode": false, + "value": " +", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " +", + "unicode": false, + "value": " +", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": true, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "targetDirs", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " +", + "unicode": false, + "value": " +", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " +", + "unicode": false, + "value": " +", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " +", + "unicode": false, + "value": "", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings test encapsed variable 1`] = ` +Program { + "children": [ + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""Hello $obj->name !"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "Hello ", + "unicode": false, + "value": "Hello ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "name", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": " !", + "unicode": false, + "value": " !", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""Hello $obj->foo->bar !"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "Hello ", + "unicode": false, + "value": "Hello ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "->bar !", + "unicode": false, + "value": "->bar !", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + Echo { + "expressions": [ + Encapsed { + "kind": "encapsed", + "raw": ""Hello $obj[1]->foo !"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "Hello ", + "unicode": false, + "value": "Hello ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "obj", + }, + }, + "kind": "encapsedpart", + "syntax": "simple", + }, + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "->foo !", + "unicode": false, + "value": "->foo !", + }, + "kind": "encapsedpart", + "syntax": null, + }, + ], + }, + ], + "kind": "echo", + "shortForm": false, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test strings test heredoc end of doc 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "label": "EOF2", + "raw": "<<", + 1, + 18, + 20, + ], + ], +} +`; diff --git a/test/snapshot/__snapshots__/trait.test.js.snap b/test/snapshot/__snapshots__/trait.test.js.snap new file mode 100644 index 000000000..eec7a3c38 --- /dev/null +++ b/test/snapshot/__snapshots__/trait.test.js.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`trait trait name as identifier 1`] = ` +Program { + "children": [ + Trait { + "body": [], + "kind": "trait", + "name": Identifier { + "kind": "identifier", + "name": "A", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/traitprecedence.test.js.snap b/test/snapshot/__snapshots__/traitprecedence.test.js.snap new file mode 100644 index 000000000..112fc3282 --- /dev/null +++ b/test/snapshot/__snapshots__/traitprecedence.test.js.snap @@ -0,0 +1,85 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`traitprecedence simple 1`] = ` +Program { + "children": [ + Class { + "attrGroups": [], + "body": [ + TraitUse { + "adaptations": [ + TraitPrecedence { + "instead": [ + Name { + "kind": "name", + "name": "A", + "resolution": "uqn", + }, + ], + "kind": "traitprecedence", + "method": Identifier { + "kind": "identifier", + "name": "smallTalk", + }, + "trait": Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + }, + TraitPrecedence { + "instead": [ + Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + ], + "kind": "traitprecedence", + "method": Identifier { + "kind": "identifier", + "name": "bigTalk", + }, + "trait": Name { + "kind": "name", + "name": "A", + "resolution": "uqn", + }, + }, + ], + "kind": "traituse", + "traits": [ + Name { + "kind": "name", + "name": "A", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "B", + "resolution": "uqn", + }, + ], + }, + ], + "extends": Name { + "kind": "name", + "name": "Base", + "resolution": "uqn", + }, + "implements": null, + "isAbstract": false, + "isAnonymous": false, + "isFinal": false, + "isReadonly": false, + "kind": "class", + "name": Identifier { + "kind": "identifier", + "name": "MyHelloWorld", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/try.test.js.snap b/test/snapshot/__snapshots__/try.test.js.snap new file mode 100644 index 000000000..b89c6a8fb --- /dev/null +++ b/test/snapshot/__snapshots__/try.test.js.snap @@ -0,0 +1,679 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`boolean finally 1`] = ` +Program { + "children": [ + Try { + "always": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something_other", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "catch", + "variable": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "what": [ + Name { + "kind": "name", + "name": "Exception", + "resolution": "uqn", + }, + ], + }, + ], + "kind": "try", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`boolean fully qualified name #2 1`] = ` +Program { + "children": [ + Try { + "always": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "catch", + "variable": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "what": [ + Name { + "kind": "name", + "name": "\\Exception\\Foo", + "resolution": "fqn", + }, + ], + }, + ], + "kind": "try", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`boolean fully qualified name 1`] = ` +Program { + "children": [ + Try { + "always": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "catch", + "variable": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "what": [ + Name { + "kind": "name", + "name": "\\Exception", + "resolution": "fqn", + }, + ], + }, + ], + "kind": "try", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`boolean multiple catch #2 1`] = ` +Program { + "children": [ + Try { + "always": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "catch", + "variable": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "what": [ + Name { + "kind": "name", + "name": "MyException", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "Foo\\Exception", + "resolution": "qn", + }, + Name { + "kind": "name", + "name": "\\Exception", + "resolution": "fqn", + }, + Name { + "kind": "name", + "name": "\\Exception\\Foo", + "resolution": "fqn", + }, + Name { + "kind": "name", + "name": "Exception", + "resolution": "rn", + }, + ], + }, + ], + "kind": "try", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`boolean multiple catch 1`] = ` +Program { + "children": [ + Try { + "always": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "catch", + "variable": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "what": [ + Name { + "kind": "name", + "name": "MyException", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "MyOtherException", + "resolution": "uqn", + }, + ], + }, + ], + "kind": "try", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`boolean multiple catch without variable 1`] = ` +Program { + "children": [ + Try { + "always": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "catch", + "variable": null, + "what": [ + Name { + "kind": "name", + "name": "MyException", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "MyOtherException", + "resolution": "uqn", + }, + ], + }, + ], + "kind": "try", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`boolean qualified name 1`] = ` +Program { + "children": [ + Try { + "always": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "catch", + "variable": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "what": [ + Name { + "kind": "name", + "name": "Foo\\Exception", + "resolution": "qn", + }, + ], + }, + ], + "kind": "try", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`boolean relative name 1`] = ` +Program { + "children": [ + Try { + "always": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "catch", + "variable": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "what": [ + Name { + "kind": "name", + "name": "Exception", + "resolution": "rn", + }, + ], + }, + ], + "kind": "try", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`boolean simple 1`] = ` +Program { + "children": [ + Try { + "always": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "catch", + "variable": Variable { + "curly": false, + "kind": "variable", + "name": "e", + }, + "what": [ + Name { + "kind": "name", + "name": "Exception", + "resolution": "uqn", + }, + ], + }, + ], + "kind": "try", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`boolean without variable 1`] = ` +Program { + "children": [ + Try { + "always": null, + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "call", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "catches": [ + Catch { + "body": Block { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "do_something", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "kind": "catch", + "variable": null, + "what": [ + Name { + "kind": "name", + "name": "Exception", + "resolution": "uqn", + }, + ], + }, + ], + "kind": "try", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/typereference.test.js.snap b/test/snapshot/__snapshots__/typereference.test.js.snap new file mode 100644 index 000000000..2bf7a4023 --- /dev/null +++ b/test/snapshot/__snapshots__/typereference.test.js.snap @@ -0,0 +1,1801 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`typereference array (argument) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "array", + "raw": "ARRAY", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference array (argument) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference array (return type declarations) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "array", + "raw": "ARRAY", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference array (return type declarations) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "array", + "raw": "array", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference bool (argument) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "bool", + "raw": "BOOL", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference bool (argument) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "bool", + "raw": "bool", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference bool (return type declarations) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "bool", + "raw": "BOOL", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference bool (return type declarations) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "bool", + "raw": "bool", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference callable (argument) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "CALLABLE", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference callable (argument) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "callable", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference callable (return type declarations) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "CALLABLE", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference callable (return type declarations) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "callable", + "raw": "callable", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference class (2) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "Foo\\Foo", + "resolution": "qn", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference class (3) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference class (4) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": Name { + "kind": "name", + "name": "Foo\\Foo", + "resolution": "qn", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference class 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference float (argument) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "float", + "raw": "FLOAT", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference float (argument) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference float (return type declarations) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "float", + "raw": "FLOAT", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference float (return type declarations) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "float", + "raw": "float", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference int (argument) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "INT", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference int (argument) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference int (return type declarations) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "INT", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference int (return type declarations) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "int", + "raw": "int", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference iterable (argument) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "iterable", + "raw": "ITERABLE", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference iterable (argument) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "iterable", + "raw": "iterable", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference iterable (return type declarations) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "iterable", + "raw": "ITERABLE", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference iterable (return type declarations) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "iterable", + "raw": "iterable", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference object (argument) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "object", + "raw": "OBJECT", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference object (argument) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "object", + "raw": "object", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference object (return type declarations) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "object", + "raw": "OBJECT", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference object (return type declarations) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "object", + "raw": "object", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference string (argument) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "string", + "raw": "STRING", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference string (argument) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference string (return type declarations) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "string", + "raw": "STRING", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference string (return type declarations) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "string", + "raw": "string", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference void (argument) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "void", + "raw": "VOID", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference void (argument) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": TypeReference { + "kind": "typereference", + "name": "void", + "raw": "void", + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference void (return type declarations) (uppercase) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "void", + "raw": "VOID", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`typereference void (return type declarations) 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "arg", + }, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": TypeReference { + "kind": "typereference", + "name": "void", + "raw": "void", + }, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/unary.test.js.snap b/test/snapshot/__snapshots__/unary.test.js.snap new file mode 100644 index 000000000..8a029bc00 --- /dev/null +++ b/test/snapshot/__snapshots__/unary.test.js.snap @@ -0,0 +1,593 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test unary boolean 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "!", + "what": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary multiple (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Pre { + "kind": "pre", + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary multiple (3) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": Unary { + "kind": "unary", + "parenthesizedExpression": true, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary multiple (4) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Unary { + "kind": "unary", + "parenthesizedExpression": true, + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary multiple (5) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "!", + "what": Unary { + "kind": "unary", + "type": "!", + "what": Unary { + "kind": "unary", + "type": "!", + "what": Unary { + "kind": "unary", + "type": "!", + "what": Unary { + "kind": "unary", + "type": "!", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary multiple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "!", + "what": Unary { + "kind": "unary", + "type": "!", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary multiple 2`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "~", + "what": Unary { + "kind": "unary", + "type": "~", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary number (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": Number { + "kind": "number", + "value": "100", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary number (3) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "~", + "what": Number { + "kind": "number", + "value": "100", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary number (4) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "!", + "what": Number { + "kind": "number", + "value": "100", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary number 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Number { + "kind": "number", + "value": "100", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary parens (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "!", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + "parenthesizedExpression": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary parens (3) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "parenthesizedExpression": true, + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary parens (4) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + "parenthesizedExpression": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary parens (5) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "parenthesizedExpression": true, + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary parens (6) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + "parenthesizedExpression": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary parens (7) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "~", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + "parenthesizedExpression": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary parens (8) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "parenthesizedExpression": true, + "type": "~", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary parens (9) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "parenthesizedExpression": true, + "type": "-", + "what": Number { + "kind": "number", + "value": "100", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary parens (10) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": Number { + "kind": "number", + "parenthesizedExpression": true, + "value": "100", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary parens 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "parenthesizedExpression": true, + "type": "!", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "!", + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary string (2) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "-", + "what": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""string"", + "unicode": false, + "value": "string", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary string (3) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "~", + "what": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""string"", + "unicode": false, + "value": "string", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary string (4) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "!", + "what": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""string"", + "unicode": false, + "value": "string", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unary string 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Unary { + "kind": "unary", + "type": "+", + "what": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""string"", + "unicode": false, + "value": "string", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/union.test.js.snap b/test/snapshot/__snapshots__/union.test.js.snap new file mode 100644 index 000000000..0b7b3e73a --- /dev/null +++ b/test/snapshot/__snapshots__/union.test.js.snap @@ -0,0 +1,597 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test unions intersection mixed with union 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "baz", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [ + Error { + "expected": undefined, + "kind": "error", + "line": 1, + "message": "Unexpect token "|", "|" and "&" can not be mixed on line 1", + "token": undefined, + }, + ], + "kind": "program", +} +`; + +exports[`Test unions intersection with reference 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": true, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unions intersection with three types 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "baz", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unions intersection with variadic 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": true, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unions simple intersection 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": IntersectionType { + "kind": "intersectiontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unions simple union 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unions union mixed with intersection 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "baz", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [ + Error { + "expected": undefined, + "kind": "error", + "line": 1, + "message": "Unexpect token "&", "|" and "&" can not be mixed on line 1", + "token": undefined, + }, + ], + "kind": "program", +} +`; + +exports[`Test unions union with reference 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": true, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unions union with three types 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "baz", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test unions union with variadic 1`] = ` +Program { + "children": [ + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": Identifier { + "kind": "identifier", + "name": "test", + }, + "nullable": false, + "readonly": false, + "type": UnionType { + "kind": "uniontype", + "name": null, + "types": [ + Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + Name { + "kind": "name", + "name": "bar", + "resolution": "uqn", + }, + ], + }, + "value": null, + "variadic": true, + }, + ], + "attrGroups": [], + "body": Block { + "children": [], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/unset.test.js.snap b/test/snapshot/__snapshots__/unset.test.js.snap new file mode 100644 index 000000000..6a4fb6d91 --- /dev/null +++ b/test/snapshot/__snapshots__/unset.test.js.snap @@ -0,0 +1,92 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`unset multiple 1`] = ` +Program { + "children": [ + Unset { + "kind": "unset", + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`unset simple 1`] = ` +Program { + "children": [ + Unset { + "kind": "unset", + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`unset trailing comma #2 1`] = ` +Program { + "children": [ + Unset { + "kind": "unset", + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + ], + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`unset trailing comma 1`] = ` +Program { + "children": [ + Unset { + "kind": "unset", + "variables": [ + Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + ], + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/usegroup.test.js.snap b/test/snapshot/__snapshots__/usegroup.test.js.snap new file mode 100644 index 000000000..c7d089fdb --- /dev/null +++ b/test/snapshot/__snapshots__/usegroup.test.js.snap @@ -0,0 +1,227 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`usegroup multiple 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "Another", + }, + "kind": "useitem", + "name": "My\\Full\\Classname", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "My\\Full\\NSname", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`usegroup multiple 2 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "Another", + }, + "kind": "useitem", + "name": "My\\Full\\Classname", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "My\\Full\\NSname", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "\\Full\\NSname\\With\\Leading\\Backslash", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`usegroup nested 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "ClassA", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "ClassB", + "type": null, + }, + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "C", + }, + "kind": "useitem", + "name": "ClassC", + "type": null, + }, + ], + "kind": "usegroup", + "name": "some\\my_namespace", + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`usegroup nested 2 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "fn_a", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "fn_b", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "fn_c", + "type": null, + }, + ], + "kind": "usegroup", + "name": "some\\my_namespace", + "type": "function", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`usegroup nested 3 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "ConstA", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "ConstB", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "ConstC", + "type": null, + }, + ], + "kind": "usegroup", + "name": "some\\my_namespace", + "type": "const", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`usegroup nested 4 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "SubnamespaceOne\\ClassA", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "SubnamespaceOne\\ClassB", + "type": null, + }, + ], + "kind": "usegroup", + "name": "Vendor\\Package\\SomeNamespace", + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`usegroup simple 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "Another", + }, + "kind": "useitem", + "name": "My\\Full\\Classname", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/useitem.test.js.snap b/test/snapshot/__snapshots__/useitem.test.js.snap new file mode 100644 index 000000000..7e6a5b3f8 --- /dev/null +++ b/test/snapshot/__snapshots__/useitem.test.js.snap @@ -0,0 +1,436 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`useitem importing a class 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "some\\my_namespace\\ClassC", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`useitem importing a class with type 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "C", + }, + "kind": "useitem", + "name": "some\\my_namespace\\ClassC", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`useitem importing a constant 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "My\\Full\\CONSTANT", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": "const", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`useitem importing a constant with type 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "MY_CONST", + }, + "kind": "useitem", + "name": "My\\Full\\CONSTANT", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": "const", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`useitem importing a function 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "My\\Full\\functionName", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": "function", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`useitem importing a function with type 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "func", + }, + "kind": "useitem", + "name": "My\\Full\\functionName", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": "function", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`useitem invalid use 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": "function", + }, + ExpressionStatement { + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "kind": "expressionstatement", + }, + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "FOO", + "type": null, + }, + UseItem { + "alias": null, + "kind": "useitem", + "name": "BAR", + "type": null, + }, + ], + "kind": "usegroup", + "name": "", + "type": "const", + }, + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "foo", + "type": null, + }, + ], + "kind": "usegroup", + "name": "some", + "type": null, + }, + ExpressionStatement { + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "error", + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + _Function { + "arguments": [ + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": null, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + Parameter { + "attrGroups": [], + "byref": false, + "flags": 0, + "kind": "parameter", + "name": null, + "nullable": false, + "readonly": false, + "type": null, + "value": null, + "variadic": false, + }, + ], + "attrGroups": [], + "body": null, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": false, + }, + "nullable": false, + "type": null, + }, + ExpressionStatement { + "expression": undefined, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": 105, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '$foo' (T_VARIABLE), expecting T_STRING on line 1", + "token": "'$foo' (T_VARIABLE)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '$foo' (T_VARIABLE), expecting ';' on line 1", + "token": "'$foo' (T_VARIABLE)", + }, + Error { + "expected": "}", + "kind": "error", + "line": 8, + "message": "Parse Error : syntax error, unexpected '$error' (T_VARIABLE), expecting '}' on line 8", + "token": "'$error' (T_VARIABLE)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 8, + "message": "Parse Error : syntax error, unexpected '$error' (T_VARIABLE), expecting ';' on line 8", + "token": "'$error' (T_VARIABLE)", + }, + Error { + "expected": ";", + "kind": "error", + "line": 8, + "message": "Parse Error : syntax error, unexpected ',', expecting ';' on line 8", + "token": "','", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 8, + "message": "Parse Error : syntax error, unexpected ',' on line 8", + "token": "','", + }, + Error { + "expected": ";", + "kind": "error", + "line": 9, + "message": "Parse Error : syntax error, unexpected 'function' (T_FUNCTION), expecting ';' on line 9", + "token": "'function' (T_FUNCTION)", + }, + Error { + "expected": "(", + "kind": "error", + "line": 9, + "message": "Parse Error : syntax error, unexpected '$bar' (T_VARIABLE), expecting '(' on line 9", + "token": "'$bar' (T_VARIABLE)", + }, + Error { + "expected": "(", + "kind": "error", + "line": 9, + "message": "Parse Error : syntax error, unexpected ',', expecting '(' on line 9", + "token": "','", + }, + Error { + "expected": 222, + "kind": "error", + "line": 9, + "message": "Parse Error : syntax error, unexpected ',', expecting T_VARIABLE on line 9", + "token": "','", + }, + Error { + "expected": 222, + "kind": "error", + "line": 10, + "message": "Parse Error : syntax error, unexpected '}', expecting T_VARIABLE on line 10", + "token": "'}'", + }, + Error { + "expected": [ + ",", + ")", + ], + "kind": "error", + "line": 10, + "message": "Parse Error : syntax error, unexpected '}' on line 10", + "token": "'}'", + }, + Error { + "expected": ")", + "kind": "error", + "line": 10, + "message": "Parse Error : syntax error, unexpected '}', expecting ')' on line 10", + "token": "'}'", + }, + Error { + "expected": "{", + "kind": "error", + "line": 10, + "message": "Parse Error : syntax error, unexpected '}', expecting '{' on line 10", + "token": "'}'", + }, + Error { + "expected": "EXPR", + "kind": "error", + "line": 10, + "message": "Parse Error : syntax error, unexpected '}' on line 10", + "token": "'}'", + }, + ], + "kind": "program", +} +`; + +exports[`useitem simple 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "My\\Full\\NSname", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`useitem simple 2 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": null, + "kind": "useitem", + "name": "ArrayObject", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`useitem with type 1`] = ` +Program { + "children": [ + UseGroup { + "items": [ + UseItem { + "alias": Identifier { + "kind": "identifier", + "name": "Another", + }, + "kind": "useitem", + "name": "My\\Full\\Classname", + "type": null, + }, + ], + "kind": "usegroup", + "name": null, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/variable.test.js.snap b/test/snapshot/__snapshots__/variable.test.js.snap new file mode 100644 index 000000000..309f8dd3b --- /dev/null +++ b/test/snapshot/__snapshots__/variable.test.js.snap @@ -0,0 +1,1526 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Test variables Chained encapsed vars 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""{$a->foo()[$bar[$foo]]}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + "what": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables Check errors should be ? 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "?", + }, + "operator": "=", + "right": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": [ + "{", + "$", + 222, + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '?' on line 1", + "token": "'?'", + }, + ], + "kind": "program", +} +`; + +exports[`Test variables Check errors should fail $foo->bar::! 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "!", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": [ + 105, + 222, + "$", + "{", + ], + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '!' on line 1", + "token": "'!'", + }, + ], + "kind": "program", +} +`; + +exports[`Test variables Check errors should fail foo::bar::baz 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "baz", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": undefined, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '::' (T_DOUBLE_COLON) on line 1", + "token": "'::' (T_DOUBLE_COLON)", + }, + ], + "kind": "program", +} +`; + +exports[`Test variables Check errors should fail on double static lookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "baz", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Name { + "kind": "name", + "name": "this", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": undefined, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '::' (T_DOUBLE_COLON) on line 1", + "token": "'::' (T_DOUBLE_COLON)", + }, + ], + "kind": "program", +} +`; + +exports[`Test variables Check errors should fail on property lookup on static lookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "baz", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [ + Error { + "expected": undefined, + "kind": "error", + "line": 1, + "message": "Parse Error : syntax error, unexpected '->' (T_OBJECT_OPERATOR) on line 1", + "token": "'->' (T_OBJECT_OPERATOR)", + }, + ], + "kind": "program", +} +`; + +exports[`Test variables Class constants 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": StaticReference { + "kind": "staticreference", + "raw": "static", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": SelfReference { + "kind": "selfreference", + "raw": "self", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": ParentReference { + "kind": "parentreference", + "raw": "parent", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "class", + }, + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "qux", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""baz"", + "unicode": false, + "value": "baz", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables Dynamic variables 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": true, + "kind": "variable", + "name": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + "type": ".", + }, + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": OffsetLookup { + "kind": "offsetlookup", + "offset": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + "type": ".", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""bar"", + "unicode": false, + "value": "bar", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables Encaps var offset 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""{$a[1]}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""{$a["a"]}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""a"", + "unicode": false, + "value": "a", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": Encapsed { + "kind": "encapsed", + "raw": ""{$a[$b]}"", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables Variable chains 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "2", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "what": Name { + "kind": "name", + "name": "foo", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables array destructuring 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": List { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "id1", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "name1", + }, + }, + ], + "kind": "list", + "shortForm": true, + }, + "operator": "=", + "right": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "0", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "data", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables default variables 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + "operator": "=", + "right": String { + "isDoubleQuote": true, + "kind": "string", + "raw": ""foo"", + "unicode": false, + "value": "foo", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": AssignRef { + "kind": "assignref", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "b", + }, + "right": Variable { + "curly": false, + "kind": "variable", + "name": "c", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "b", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "a", + }, + }, + "operator": "=", + "right": Boolean { + "kind": "boolean", + "raw": "true", + "value": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables fix #167 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Call { + "arguments": [], + "kind": "call", + "what": StaticLookup { + "kind": "staticlookup", + "offset": Literal { + "kind": "literal", + "value": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'baz'", + "unicode": false, + "value": "baz", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Call { + "arguments": [], + "kind": "call", + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'baz'", + "unicode": false, + "value": "baz", + }, + "what": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables fix #185 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "0", + }, + "parenthesizedExpression": true, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "parenthesizedExpression": true, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "0", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "0", + }, + "parenthesizedExpression": true, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "1", + }, + "parenthesizedExpression": true, + "what": OffsetLookup { + "kind": "offsetlookup", + "offset": Number { + "kind": "number", + "value": "0", + }, + "parenthesizedExpression": true, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": StaticLookup { + "kind": "staticlookup", + "offset": Identifier { + "kind": "identifier", + "name": "bar", + }, + "what": New { + "arguments": [], + "kind": "new", + "parenthesizedExpression": true, + "what": Name { + "kind": "name", + "name": "Foo", + "resolution": "uqn", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "wrap", + }, + "what": Call { + "arguments": [ + PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "resource", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "this", + }, + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables fix 248 - broken ast for \`$$$$$\` 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables fix 248 - test curly 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": EncapsedPart { + "curly": false, + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": PropertyLookup { + "kind": "propertylookup", + "offset": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + "kind": "expressionstatement", + }, + ExpressionStatement { + "expression": OffsetLookup { + "kind": "offsetlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + "what": PropertyLookup { + "kind": "propertylookup", + "offset": Identifier { + "kind": "identifier", + "name": "foo_", + }, + "what": Variable { + "curly": false, + "kind": "variable", + "name": "bar", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables fix 253 - can't be parsed \`global\` with multiple \`$\` 1`] = ` +Program { + "children": [ + Global { + "items": [ + Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "foo", + }, + }, + ], + "kind": "global", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables simple variable #2 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Variable { + "curly": true, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables simple variable #3 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Variable { + "curly": true, + "kind": "variable", + "name": Bin { + "kind": "bin", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "right": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "'foo'", + "unicode": false, + "value": "foo", + }, + "type": "+", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables simple variable #4 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables simple variable 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + "operator": "=", + "right": Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`Test variables valid offset lookup 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": StaticLookup { + "kind": "staticlookup", + "offset": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": Variable { + "curly": false, + "kind": "variable", + "name": "property", + }, + }, + }, + }, + }, + "what": Call { + "arguments": [ + Variable { + "curly": false, + "kind": "variable", + "name": "var", + }, + ], + "kind": "call", + "what": Name { + "kind": "name", + "name": "get_class", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/yield.test.js.snap b/test/snapshot/__snapshots__/yield.test.js.snap new file mode 100644 index 000000000..826653218 --- /dev/null +++ b/test/snapshot/__snapshots__/yield.test.js.snap @@ -0,0 +1,263 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`yield assign (key and value) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "data", + }, + "operator": "=", + "right": Yield { + "key": Variable { + "curly": false, + "kind": "variable", + "name": "key", + }, + "kind": "yield", + "parenthesizedExpression": true, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`yield assign (parens) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "data", + }, + "operator": "=", + "right": Yield { + "key": null, + "kind": "yield", + "parenthesizedExpression": true, + "value": Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`yield assign 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Assign { + "kind": "assign", + "left": Variable { + "curly": false, + "kind": "variable", + "name": "data", + }, + "operator": "=", + "right": Yield { + "key": null, + "kind": "yield", + "value": Variable { + "curly": false, + "kind": "variable", + "name": "value", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`yield expression as generator key 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Yield { + "key": Encapsed { + "kind": "encapsed", + "raw": ""bar {$test}" ", + "type": "string", + "value": [ + EncapsedPart { + "curly": false, + "expression": String { + "isDoubleQuote": false, + "kind": "string", + "raw": "bar ", + "unicode": false, + "value": "bar ", + }, + "kind": "encapsedpart", + "syntax": null, + }, + EncapsedPart { + "curly": false, + "expression": Variable { + "curly": false, + "kind": "variable", + "name": "test", + }, + "kind": "encapsedpart", + "syntax": "complex", + }, + ], + }, + "kind": "yield", + "value": Number { + "kind": "number", + "value": "123", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`yield inside function 1`] = ` +Program { + "children": [ + _Function { + "arguments": [], + "attrGroups": [], + "body": Block { + "children": [ + ExpressionStatement { + "expression": Yield { + "key": null, + "kind": "yield", + "value": Variable { + "curly": false, + "kind": "variable", + "name": "i", + }, + }, + "kind": "expressionstatement", + }, + ], + "kind": "block", + }, + "byref": false, + "kind": "function", + "name": Identifier { + "kind": "identifier", + "name": "foo", + }, + "nullable": false, + "type": null, + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`yield null 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Yield { + "key": null, + "kind": "yield", + "value": null, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`yield simple (key and value) 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Yield { + "key": Variable { + "curly": false, + "kind": "variable", + "name": "id", + }, + "kind": "yield", + "value": Variable { + "curly": false, + "kind": "variable", + "name": "fields", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`yield simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": Yield { + "key": null, + "kind": "yield", + "value": Variable { + "curly": false, + "kind": "variable", + "name": "i", + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/__snapshots__/yieldfrom.test.js.snap b/test/snapshot/__snapshots__/yieldfrom.test.js.snap new file mode 100644 index 000000000..b75e85d8b --- /dev/null +++ b/test/snapshot/__snapshots__/yieldfrom.test.js.snap @@ -0,0 +1,141 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`yieldfrom array 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": YieldFrom { + "kind": "yieldfrom", + "value": Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "3", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "4", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`yieldfrom new 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": YieldFrom { + "kind": "yieldfrom", + "value": New { + "arguments": [ + Array { + "items": [ + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "5", + }, + }, + Entry { + "byRef": false, + "key": null, + "kind": "entry", + "unpack": false, + "value": Number { + "kind": "number", + "value": "6", + }, + }, + ], + "kind": "array", + "shortForm": true, + }, + ], + "kind": "new", + "what": Name { + "kind": "name", + "name": "ArrayIterator", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`yieldfrom return 1`] = ` +Program { + "children": [ + Return { + "expr": YieldFrom { + "kind": "yieldfrom", + "value": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "nine_ten", + "resolution": "uqn", + }, + }, + }, + "kind": "return", + }, + ], + "errors": [], + "kind": "program", +} +`; + +exports[`yieldfrom simple 1`] = ` +Program { + "children": [ + ExpressionStatement { + "expression": YieldFrom { + "kind": "yieldfrom", + "value": Call { + "arguments": [], + "kind": "call", + "what": Name { + "kind": "name", + "name": "from", + "resolution": "uqn", + }, + }, + }, + "kind": "expressionstatement", + }, + ], + "errors": [], + "kind": "program", +} +`; diff --git a/test/snapshot/acid.test.js b/test/snapshot/acid.test.js new file mode 100644 index 000000000..f3bde007b --- /dev/null +++ b/test/snapshot/acid.test.js @@ -0,0 +1,177 @@ +const parser = require("../main"); + +describe("Acid", () => { + it("level 1", () => { + expect( + parser.parseCode( + `#!/usr/bin/php + +Hello 'achoum', + 'bashful' => 'tadah' + ]; + /** + * Something is done here + */ + final public function doSomething() { + // do not wanna do + foreach($this->dwarf as $name => $greeting) { + echo "Hey ho $name, $greeting !"; + continue $foo; + } + throw new \\ComeToHome('Thats it'); + } + } + + interface Miror extends Object { + public function Am_I_Uggly() : bool; + protected function broken() : bool; + static protected function isWhiteSnowAlive() : bool; + } + + function iter() { + yield 'ator' => $foo; + yield from iter(50); + } + + trait Line { + public function draw(bool $arrow = false) : string { + switch($this->style) { + case 'dot': + case 'point': + $body = '......'; + break; + default: + $body = '-----'; + break; + } + return $body . ($arrow ? '>' : ''); + } + private function shuut() { + return __NAMESPACE__; + } + } + + // this is SPARTA ! + function sparta() : ?int { + global $persians; + + $index = -1; +next: + $guy = $persians[++$index]; + if(rand(0, 10)>5 || false) { + @$guy->kill(); + } else { + $guy->kick(...$foo); + } + if ((int)$index < count($persians)) goto next; + + return 300 | 5; + } + + $foo = function(?int $bar = 42) use($something) : bool { + static $banana; + if($bar > fooBar::NUMBAR) { + while($bar) { + if ((int)calculateMeaningOfLife() === 42) { + break foo; + } else continue; + } + do { + ?> + Caesar: here I was + crazy()->boom([1, 2, 3]); + } catch(Coco|Nut $ex) { + $ex->printStackTrace(); + } finally { + if (isset($bipbip, $ex)) unset($bipbip, $ex); + return (new class extends fooBar { + function goatIt() { + return "meeeh"; + } + })->goatIt(); + } + } else { + for($i = 0; $i < count($this->banana); $i++) { + $x %= ($i * 2) / ($i - 1); + $what = $this->$x[++$i] ? 'yes!': 'noo!'; + } + // @todo $this->a_$foo + return $$foo ?? false; + } + return empty(namespace\\FOOBAR); + }; + + if ($foo): + echo \`bar&\`; + elseif ($bar): + echo \`ls -larth\`; + endif; + + // list version + list(,$a, list($b, $c)) = [1, [2, 3]]; + [,$a,[$b, ,$c]] = $f; + print(<< { + it("deference array", () => { + expect( + parser.parseEval( + ["$a = [", '"a", "b"', "]($foo)[$foo->bar()[1]]->foo()"].join("\r"), + ), + ).toMatchSnapshot(); + }); + + it("of strings", () => { + expect( + parser.parseEval('array("item1", "item2", "item3")'), + ).toMatchSnapshot(); + }); + + it("of numbers", () => { + expect(parser.parseEval("array(1, 2.5, 0x1000)")).toMatchSnapshot(); + }); + + it("of strings and numbers", () => { + expect(parser.parseEval('array(1, "item2", 3, "item4")')).toMatchSnapshot(); + }); + + it("of variables", () => { + expect(parser.parseEval("array($obj1, $obj2, $obj3)")).toMatchSnapshot(); + }); + + it("of objects", () => { + expect( + parser.parseEval("[new foo(), new stdClass(), new bar()]"), + ).toMatchSnapshot(); + }); + + it("of arrays", () => { + expect( + parser.parseEval(` + array( + array("item1", "item2"), + array("item3", "item4"), + array("item5", "item6") + )`), + ).toMatchSnapshot(); + }); + + describe("mixed tests / coverage", function () { + it("test empty array", function () { + expect(parser.parseEval("$a = []; $b = array();")).toMatchSnapshot(); + }); + it("test short form / keys", function () { + expect( + parser.parseEval('[0 => &$foo, $bar => "foobar"];'), + ).toMatchSnapshot(); + }); + }); + + it("single and empty", () => { + expect(parser.parseEval("array()")).toMatchSnapshot(); + }); + + it("single and empty (short form)", () => { + expect(parser.parseEval("[]")).toMatchSnapshot(); + }); + + it("array without trailing commas", () => { + expect(parser.parseEval("['foo', 'bar']")).toMatchSnapshot(); + }); + + it("array without trailing commas #2", () => { + expect(parser.parseEval("['foo', 'bar']")).toMatchSnapshot(); + }); + + it("array with trailing commas #3", () => { + expect(parser.parseEval("['foo', 'bar',]")).toMatchSnapshot(); + }); + + it("array with trailing commas #4", () => { + expect(parser.parseEval("['foo', 'bar' ,]")).toMatchSnapshot(); + }); + + it("array with trailing commas #5", () => { + expect(parser.parseEval("['foo', 'bar' , ]")).toMatchSnapshot(); + }); + + it("array with multiple trailing commas", () => { + expect(parser.parseEval("['foo', 'bar',,]")).toMatchSnapshot(); + }); + + it("array with multiple trailing commas #2", () => { + expect(parser.parseEval("['foo', 'bar',,,,,]")).toMatchSnapshot(); + }); + + it("array with empty values", () => { + expect(parser.parseEval("[,,,'foo',,, 'bar',,,'baz']")).toMatchSnapshot(); + }); + + it("array with empty values #2", () => { + expect(parser.parseEval("[,,,'foo',,, 'bar',,,'baz',]")).toMatchSnapshot(); + }); + + it("array with empty values #3", () => { + expect(parser.parseEval("[,,,'foo',,, 'bar',,,'baz',,]")).toMatchSnapshot(); + }); + + it("non empty array", () => { + expect( + parser.parseEval( + "$var = [true, 1, 1.1, 'test', \"test\", [1, 2, 3], new Foo(), call(), null];", + ), + ).toMatchSnapshot(); + }); + + it("spread operator", () => { + expect( + parser.parseEval(` +$var = ['banana', 'orange', ...$parts, 'watermelon']; +$var = [...$arr1]; +$var = [0, ...$arr1]; +$var = array(...$arr1, ...$arr2, 111); +$var = [...$arr1, ...$arr1]; +$var = [...getArr(), 'c']; +$var = [...new ArrayIterator(['a', 'b', 'c'])]; +`), + ).toMatchSnapshot(); + }); + + it("spread operator with reference", function () { + const astErr = parser.parseEval(`$var = [...&$arr];`, { + parser: { + suppressErrors: true, + }, + }); + expect(astErr).toMatchSnapshot(); + }); + + it("byRef", () => { + expect( + parser.parseEval(` +$var = [1, 'test', &$var, 'test' => &$var]; +`), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/arrowfunc.test.js b/test/snapshot/arrowfunc.test.js new file mode 100644 index 000000000..1031e0cda --- /dev/null +++ b/test/snapshot/arrowfunc.test.js @@ -0,0 +1,53 @@ +const parser = require("../main"); + +describe("arrow function", () => { + it.each([ + ["simple", '$var = fn() => "something";'], + ["argument", '$var = fn($arg) => "something";'], + ["argument by ref", '$var = fn(&$arg) => "something";'], + ["arguments", '$var = fn($arg, $arg, $arg) => "something";'], + ["return type", '$var = fn(): ?string => "something";'], + ["inside call", `call(fn($arg) => $arg);`], + ])("%s", function (_, code) { + expect(parser.parseEval(code)).toMatchSnapshot(); + }); + + it("error / fn passes on php7.3", () => { + expect( + parser.parseEval(`function fn($arg) { return $arg; }`, { + parser: { + version: "7.3", // disable the php 7.4 support + }, + }), + ).toMatchSnapshot(); + }); + it("error / fn fails on php7.4", () => { + expect( + parser.parseEval(`function fn($arg) { return $arg; }`, { + parser: { + version: "7.4", // enable the php 7.4 support + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + }); + it("error / empty not allowed", () => { + expect( + parser.parseEval("$var = fn() => ;", { + parser: { + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + }); + it("error / arrow functions before PHP 7.4", () => { + expect( + parser.parseEval(`$fn1 = fn($x) => $x + $y;`, { + parser: { + version: "7.3", + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/assign.test.js b/test/snapshot/assign.test.js new file mode 100644 index 000000000..696e532b3 --- /dev/null +++ b/test/snapshot/assign.test.js @@ -0,0 +1,67 @@ +const parser = require("../main"); + +describe("assign", () => { + it("simple", () => { + expect(parser.parseEval("$var = 1;")).toMatchSnapshot(); + }); + it("variable", () => { + expect(parser.parseEval("$var = $var;")).toMatchSnapshot(); + }); + it("multiple", () => { + expect(parser.parseEval("$var = $var = $var;")).toMatchSnapshot(); + }); + it("+=", () => { + expect(parser.parseEval("$var += $var;")).toMatchSnapshot(); + }); + it("-=", () => { + expect(parser.parseEval("$var -= $var;")).toMatchSnapshot(); + }); + it("*=", () => { + expect(parser.parseEval("$var *= $var;")).toMatchSnapshot(); + }); + it("**=", () => { + expect(parser.parseEval("$var **= $var;")).toMatchSnapshot(); + }); + it("/=", () => { + expect(parser.parseEval("$var /= $var;")).toMatchSnapshot(); + }); + it(".=", () => { + expect(parser.parseEval("$var .= $var;")).toMatchSnapshot(); + }); + it("%=", () => { + expect(parser.parseEval("$var %= $var;")).toMatchSnapshot(); + }); + it("&=", () => { + expect(parser.parseEval("$var &= $var;")).toMatchSnapshot(); + }); + it("|=", () => { + expect(parser.parseEval("$var |= $var;")).toMatchSnapshot(); + }); + it("^=", () => { + expect(parser.parseEval("$var ^= $var;")).toMatchSnapshot(); + }); + it("<<=", () => { + expect(parser.parseEval("$var <<= $var;")).toMatchSnapshot(); + }); + it(">>=", () => { + expect(parser.parseEval("$var >>= $var;")).toMatchSnapshot(); + }); + it("??=", () => { + expect(parser.parseEval("$var ??= $var;")).toMatchSnapshot(); + }); + it("??= with bin", () => { + expect(parser.parseEval("$var ??= $var + 10;")).toMatchSnapshot(); + }); + it("??= (php < 7)", function () { + const astErr = parser.parseEval(`$var ??= $var;`, { + parser: { + version: "5.6", + suppressErrors: true, + }, + }); + expect(astErr).toMatchSnapshot(); + }); + it("with ref", () => { + expect(parser.parseEval("$bar = &$foo;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/ast.test.js b/test/snapshot/ast.test.js new file mode 100644 index 000000000..812d6c3cc --- /dev/null +++ b/test/snapshot/ast.test.js @@ -0,0 +1,118 @@ +const parser = require("../main"); + +describe("Test AST structure", function () { + it("fix #127 - echo statements", () => { + expect(parser.parseEval('echo "hello"; ?> world')).toMatchSnapshot(); + }); + + it("fix #127 - inline", function () { + expect(parser.parseEval("?>?>?>")).toMatchSnapshot(); + }); + + it("fix #370 - nullkeyword", function () { + expect(parser.parseEval("$a = Null;")).toMatchSnapshot(); + }); + + it("fix #370 - classreference instead identifier(classreferent)", function () { + expect(parser.parseEval("$a = test;")).toMatchSnapshot(); + }); + + it("#176 - lost `?>` in program node", function () { + expect( + parser.parseCode( + ``, + null, + { + ast: { + withPositions: true, + withSource: true, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test program", function () { + expect(parser.parseEval("")).toMatchSnapshot(); + }); + it("test syntax error", function () { + const parse = function () { + parser.parseEval(` + $a = 1 + $b = 2 + `); + }; + expect(parse).toThrowErrorMatchingSnapshot(); + }); + it("test inline", function () { + expect( + parser.parseCode("Hello \n !"), + ).toMatchSnapshot(); + }); + + it("fix #120", function () { + expect(parser.parseCode("\r\n !")).toMatchSnapshot(); + }); + + it("test invalid namespace separator", function () { + expect( + parser.parseCode("\r\n !", { + parser: { suppressErrors: true }, + }), + ).toMatchSnapshot(); + }); + + it("test magics", function () { + expect(parser.parseEval("echo __FILE__, __DIR__;")).toMatchSnapshot(); + }); + it("test shell", function () { + expect(parser.parseEval("echo `ls -larth`;")).toMatchSnapshot(); + }); + it("test clone", function () { + expect(parser.parseEval("$a = clone $var;")).toMatchSnapshot(); + }); + it("test echo, isset, unset, empty", function () { + expect( + parser.parseEval(` + echo ($expr) ? "ok" : "ko"; + print "some text"; + isset($foo, $bar); + unset($var); + empty($var); + `), + ).toMatchSnapshot(); + }); + + it("test constants", function () { + expect(parser.parseEval("const FOO = 3.14;")).toMatchSnapshot(); + }); + + it("test eval", function () { + expect(parser.parseEval('eval("return true;");')).toMatchSnapshot(); + }); + it("test die/exit", function () { + expect( + parser.parseEval(` + die("bye"); + exit(-1); + `), + ).toMatchSnapshot(); + }); + + it("test coalesce operator", function () { + expect(parser.parseEval("$var = $a ?? true;")).toMatchSnapshot(); + }); + + it("test include / require", function () { + expect( + parser.parseEval(` + include "file.php"; + include_once (PATH . "/file.php"); + require "req.php"; + require_once "file.php"; + `), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/attributes.test.js b/test/snapshot/attributes.test.js new file mode 100644 index 000000000..843001e80 --- /dev/null +++ b/test/snapshot/attributes.test.js @@ -0,0 +1,318 @@ +const parser = require("../main"); + +describe("Parse Attributes", () => { + it("can parse class attributes", () => { + expect( + parser.parseEval(` + #[Deprecated] + #[replace("use NewClass")] + class DepClass {} + `), + ).toMatchSnapshot(); + }); + it("can parse method attributes", () => { + expect( + parser.parseEval(` + class Test { + #[Pure] + function m() {} + } + `), + ).toMatchSnapshot(); + }); + it("can parse param attributes", () => { + expect( + parser.parseEval(` + function f( + #[Unsigned] + int $n) {} + `), + ).toMatchSnapshot(); + }); + it("can parse params with comments", () => { + expect( + parser.parseEval( + `// Line 1 + #[ Pure ( ) /* Pure */ ] + // Line 3 + #[ + // Try using b + Deprecated + ] + function a(#[ Unsigned ] $a) {} + `, + { + parser: { + extractDoc: true, + }, + }, + ), + ).toMatchSnapshot(); + }); + it("can parse parms with array values", () => { + expect( + parser.parseEval(` + #[List(["a"=>1, 'b' => Test::class, 'c'=>[]])] + function a() {} + `), + ).toMatchSnapshot(); + }); + it("can parse params with argument labels", () => { + expect( + parser.parseEval(` + #[MyAttribute(value: 1234)] + function a() {} + `), + ).toMatchSnapshot(); + }); + it("can parse params with mathematical expressions", () => { + expect( + parser.parseEval( + ` + #[Att1(-20 * (+10 / 5) % 2 + 8 ** 2 - +-2)] + class A {} + `, + { parser: { extractDoc: true } }, + ), + ).toMatchSnapshot(); + }); + it("can parse params with bitwise operations", () => { + expect( + parser.parseEval( + ` + #[Att1(Att1::FOO | Att1::BAR)] + #[Att2(Att2::FOO & Att2::BAR)] + #[Att3(Att3::FOO ^ Att3::BAR)] + #[Att4(~ Att4::BAR)] + #[Att5(Att5::BAR >> 1)] + #[Att6(Att6::BAR << 1)] + class A {} + `, + { parser: { extractDoc: true } }, + ), + ).toMatchSnapshot(); + }); + it("can parse params with logical operations", () => { + expect( + parser.parseEval( + ` + #[Att1(Att1::FOO || Att1::BAR)] + #[Att2(Att2::FOO && Att2::BAR)] + #[Att3(Att3::FOO or Att3::BAR)] + #[Att4(Att4::FOO and Att4::BAR)] + #[Att5(Att5::FOO xor Att5::BAR)] + #[Att6(!Att6::FOO)] + class A {} + `, + { parser: { extractDoc: true } }, + ), + ).toMatchSnapshot(); + }); + it("can parse params with string concatenation", () => { + expect( + parser.parseEval( + ` + #[Att1(Att1::FOO . Att1::BAR)] + #[Att1(Att1::FOO.Att1::BAR)] + #[Att2("a" . "b")] + #[Att2("a"."b")] + #[Att2('a' . "b")] + #[Att2('a'."b")] + #[Att2("a" . 'b')] + #[Att2("a".'b')] + #[Att2('a' . 'b')] + #[Att2('a'.'b')] + #[Att1(Att1::FOO . "b")] + #[Att1(Att1::FOO."b")] + #[Att1(Att1::FOO . 'b')] + #[Att1(Att1::FOO.'b')] + #[Att1("a" . Att1::BAR)] + #[Att1("a".Att1::BAR)] + #[Att1('a' . Att1::BAR)] + #[Att1('a'.Att1::BAR)] + #[Att1(Att1::FOO + .Att1::BAR + )] + #[Att1(Att1::FOO. + Att1::BAR + )] + class A {} + `, + { parser: { extractDoc: true } }, + ), + ).toMatchSnapshot(); + }); + it("can parse params with end characters", () => { + expect( + parser.parseEval(` + #[End(["])}>"])] + class End {} + `), + ).toMatchSnapshot(); + }); + it("can parse multi-line attributes", () => { + expect( + parser.parseEval(` + #[ + One(), + Two(), + Three() + ] + #[Four] + class Multi {} + `), + ).toMatchSnapshot(); + }); + it("can parse anonymous function attributes", () => { + expect( + parser.parseEval(` + $a = #[Pure] fn() => true; + $b = #[A] function() {}; + `), + ).toMatchSnapshot(); + }); + it("can't parse anonymous function attributes in PHP < 8", () => { + expect(() => + parser.parseEval( + ` + $a = #[Pure] fn() => true; + `, + { + parser: { + version: "7.4", + }, + }, + ), + ).toThrow(SyntaxError); + }); + it("can parse class property attributes", () => { + expect( + parser.parseEval(` + class A { + #[B] + public B $b; + #[C] + private C $c; + #[D] + protected $d; + } + `), + ).toMatchSnapshot(); + }); + it("can parse class const attributes", () => { + expect( + parser.parseEval(` + class A { + #[B] + const B = 1; + } + `), + ).toMatchSnapshot(); + }); + it("can parse anon-class attributes", () => { + expect(parser.parseEval(`$a = new #[T] class {};`)).toMatchSnapshot(); + }); + it("can't parse anon-class attributes in PHP < 8", () => { + expect(() => + parser.parseEval(`$a = new #[T] class {};`, { + parser: { + version: "7.4", + }, + }), + ).toThrow(SyntaxError); + }); + it("can parse interface attributes", () => { + expect( + parser.parseEval(` + #[A] + interface b { + #[C] + const D = 0; + #[E] + public function f(); + } + `), + ).toMatchSnapshot(); + }); + it("can parse attributes in inner statements", () => { + expect( + parser.parseEval(` + namespace A { + function b() { + return #[C] fn() => #[Pure] function() {}; + } + }`), + ).toMatchSnapshot(); + }); + it("can parse attributes with namespace", () => { + expect( + parser.parseEval(` + #[\\JetBrains\\PhpStorm\\Pure] + function b() {} + `), + ).toMatchSnapshot(); + }); + + it("doesnt repeat attributes from previous function", () => { + expect( + parser.parseEval(` + class a { + #[Att1] + function b(){} + function c(){} + function d(){} + } + `), + ).toMatchSnapshot(); + }); + + it("parses attributes as comments for PHP < 8", () => { + expect( + parser.parseEval( + ` + #[Att1] + class a { + #[Att2] + function b(){} + } + `, + { + parser: { + version: "7.4", + extractDoc: true, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("parses this complicated edge case", () => { + expect( + parser.parseEval( + ` + use Symfony\\Component\\Validator\\Constraints as Assert; + + class ValueModel + { + #[ + Assert\\NotBlank(allowNull: false, groups: ['foo']), + Assert\\Length(max: 255, groups: ['foo']), + ] + public ?string $value = null; + }`, + ), + ).toMatchSnapshot(); + }); + + it("doesnt parse attributes for assignments", () => { + expect( + parser.parseEval( + ` + #[Att1] + $a = 1; + `, + { parser: { extractDoc: true } }, + ), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/bin.test.js b/test/snapshot/bin.test.js new file mode 100644 index 000000000..b8c7e1df4 --- /dev/null +++ b/test/snapshot/bin.test.js @@ -0,0 +1,139 @@ +const parser = require("../main"); + +describe("bin", () => { + it("|", () => { + expect(parser.parseEval("$foo | $bar;")).toMatchSnapshot(); + }); + it("&", () => { + expect(parser.parseEval("$foo & $bar;")).toMatchSnapshot(); + }); + it("^", () => { + expect(parser.parseEval("$foo ^ $bar;")).toMatchSnapshot(); + }); + it(".", () => { + expect(parser.parseEval("$foo . $bar;")).toMatchSnapshot(); + }); + it("+", () => { + expect(parser.parseEval("$foo + $bar;")).toMatchSnapshot(); + }); + it("-", () => { + expect(parser.parseEval("$foo - $bar;")).toMatchSnapshot(); + }); + it("*", () => { + expect(parser.parseEval("$foo * $bar;")).toMatchSnapshot(); + }); + it("/", () => { + expect(parser.parseEval("$foo / $bar;")).toMatchSnapshot(); + }); + it("%", () => { + expect(parser.parseEval("$foo % $bar;")).toMatchSnapshot(); + }); + it("**", () => { + expect(parser.parseEval("$foo ** $bar;")).toMatchSnapshot(); + }); + it("<<", () => { + expect(parser.parseEval("$foo << $bar;")).toMatchSnapshot(); + }); + it(">>", () => { + expect(parser.parseEval("$foo >> $bar;")).toMatchSnapshot(); + }); + it("||", () => { + expect(parser.parseEval("$foo || $bar;")).toMatchSnapshot(); + }); + it("or", () => { + expect(parser.parseEval("$foo or $bar;")).toMatchSnapshot(); + }); + it("&&", () => { + expect(parser.parseEval("$foo && $bar;")).toMatchSnapshot(); + }); + it("and", () => { + expect(parser.parseEval("$foo and $bar;")).toMatchSnapshot(); + }); + it("xor", () => { + expect(parser.parseEval("$foo xor $bar;")).toMatchSnapshot(); + }); + it("===", () => { + expect(parser.parseEval("$foo === $bar;")).toMatchSnapshot(); + }); + it("!==", () => { + expect(parser.parseEval("$foo !== $bar;")).toMatchSnapshot(); + }); + it("==", () => { + expect(parser.parseEval("$foo == $bar;")).toMatchSnapshot(); + }); + it("!=", () => { + expect(parser.parseEval("$foo != $bar;")).toMatchSnapshot(); + }); + it("<", () => { + expect(parser.parseEval("$foo < $bar;")).toMatchSnapshot(); + }); + it(">", () => { + expect(parser.parseEval("$foo > $bar;")).toMatchSnapshot(); + }); + it("<=", () => { + expect(parser.parseEval("$foo <= $bar;")).toMatchSnapshot(); + }); + it(">=", () => { + expect(parser.parseEval("$foo >= $bar;")).toMatchSnapshot(); + }); + it("<=>", () => { + expect(parser.parseEval("$foo <=> $bar;")).toMatchSnapshot(); + }); + it("instanceof", () => { + expect(parser.parseEval("$foo instanceof MyClass;")).toMatchSnapshot(); + }); + it("instanceof variable", () => { + expect(parser.parseEval("$foo instanceof $var;")).toMatchSnapshot(); + }); + it("instanceof parent", () => { + expect(parser.parseEval("$foo instanceof parent;")).toMatchSnapshot(); + }); + it("instanceof self", () => { + expect(parser.parseEval("$foo instanceof self;")).toMatchSnapshot(); + }); + it("instanceof static", () => { + expect(parser.parseEval("$foo instanceof static;")).toMatchSnapshot(); + }); + it("multiple instanceof static", () => { + expect( + parser.parseEval("$foo instanceof static && $bar instanceof self;"), + ).toMatchSnapshot(); + }); + + it("??", () => { + expect(parser.parseEval("$foo ?? $bar;")).toMatchSnapshot(); + }); + it("** right-associative", () => { + expect(parser.parseEval("$a ** $b ** $c;")).toMatchSnapshot(); + }); + it("?? right-associative", () => { + expect(parser.parseEval("$a ?? $b ?? $c;")).toMatchSnapshot(); + }); + it("?? (php < 7)", function () { + const astErr = parser.parseEval(`$var ?? $var;`, { + parser: { + version: "5.6", + suppressErrors: true, + }, + }); + expect(astErr).toMatchSnapshot(); + }); + it("assign", () => { + expect(parser.parseEval("$var = $var + $var;")).toMatchSnapshot(); + }); + it("multiple", () => { + expect(parser.parseEval("$var = $var + $var + $var;")).toMatchSnapshot(); + }); + it("parens", () => { + expect(parser.parseEval("($var + $var);")).toMatchSnapshot(); + }); + it("parens around `and`", () => { + expect(parser.parseEval("$var = ($var and $var);")).toMatchSnapshot(); + }); + it("parens around `xor`", () => { + expect(parser.parseEval("$var = ($var xor $var);")).toMatchSnapshot(); + }); + it("parens around `or`", () => { + expect(parser.parseEval("$var = ($var or $var);")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/block.test.js b/test/snapshot/block.test.js new file mode 100644 index 000000000..43dbe72ef --- /dev/null +++ b/test/snapshot/block.test.js @@ -0,0 +1,83 @@ +const parser = require("../main"); + +describe("block", () => { + it.each([ + ["single", "{ $var = 1; }"], + ["empty function block", "function foo() { /* 1 */ }"], + ["empty class block", "class foo { /* 1 */ }"], + ["empty method block", "class foo { function bar() { /* 1 */ } }"], + ["empty namespace block", "namespace foo { /* 1 */ }"], + ["empty declare block", "declare(tick=1) { /* 1 */ }"], + ["empty declare short form", "declare(tick=1): /* 1 */ ENDDECLARE;"], + ["empty switch", "switch($foo) { /* foo */ }"], + ["empty for", "for(;;) { /* foo */ }"], + ["empty foreach", "foreach($foo as $bar) { /* foo */ }"], + ["empty switch short form", "switch($foo): /* foo */ endswitch;"], + [ + "empty switch case short form", + "switch($foo): case 1: /* foo */ endswitch;", + ], + ["empty for short form", "for(;;): /* foo */ endfor;"], + [ + "empty foreach short form", + "foreach($foo as $bar): /* foo */ endforeach;", + ], + ["empty if", "if($foo) { /* foo */ }"], + ["empty statement", "/* 1 */; /* 2 */; ; /* 3 */"], + ["empty if short form", "if($foo): /* foo */ endif;"], + [ + "empty if #2 short form", + "if($foo): /* pre */ $a; /* inner */ endif; /* out */", + ], + [ + "empty if #3 short form", + "if($foo): /* foo */ elseif($bar): /* baz */ else: /* bar */ endif;", + ], + ])("%s", function (_, code) { + expect( + parser.parseEval(code, { + parser: { + extractDoc: true, + }, + }), + ).toMatchSnapshot(); + }); + it("check empty php blocks", function () { + expect( + parser.parseCode( + ` +SOME HTML OUTPUT + { + it("assign", () => { + expect(parser.parseEval("$var = true;")).toMatchSnapshot(); + }); + it("assign (2)", () => { + expect(parser.parseEval("$var = false;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/break.test.js b/test/snapshot/break.test.js new file mode 100644 index 000000000..d4db2ec99 --- /dev/null +++ b/test/snapshot/break.test.js @@ -0,0 +1,30 @@ +const parser = require("../main"); + +describe("break", () => { + it("simple", () => { + expect(parser.parseEval("break;")).toMatchSnapshot(); + }); + it("argument 0", () => { + expect(parser.parseEval("break 0;")).toMatchSnapshot(); + }); + it("argument 1", () => { + expect(parser.parseEval("break 1;")).toMatchSnapshot(); + }); + it("argument 2", () => { + expect(parser.parseEval("break 2;")).toMatchSnapshot(); + }); + it("with parens", () => { + expect(parser.parseEval("break (1);")).toMatchSnapshot(); + }); + // Deprecated since 5.4.0 + it("with expression", () => { + expect(parser.parseEval("break $var;")).toMatchSnapshot(); + }); + it("should fail when no ';' at end", function () { + expect( + parser.parseEval("break", { + parser: { suppressErrors: true }, + }), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/buffer.test.js b/test/snapshot/buffer.test.js new file mode 100644 index 000000000..be9200ab4 --- /dev/null +++ b/test/snapshot/buffer.test.js @@ -0,0 +1,8 @@ +const parser = require("../main"); + +describe("Test buffers", function () { + it("handles buffers as input", function () { + const buffer = new Buffer('echo "test"'); + expect(parser.parseEval(buffer)).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/byref.test.js b/test/snapshot/byref.test.js new file mode 100644 index 000000000..6a062130a --- /dev/null +++ b/test/snapshot/byref.test.js @@ -0,0 +1,119 @@ +const parser = require("../main"); + +describe("byref", () => { + it("variable", () => { + expect(parser.parseEval("$var = &$foo;")).toMatchSnapshot(); + }); + it("static lookup", () => { + expect(parser.parseEval("$var = &foo::$bar;")).toMatchSnapshot(); + }); + it("offset lookup", () => { + expect(parser.parseEval("$foo[&$bar];")).toMatchSnapshot(); + }); + it("new class", () => { + expect( + parser.parseEval("$a =& new foo();", { + parser: { + version: "5.6", + }, + }), + ).toMatchSnapshot(); + expect(() => { + parser.parseEval("$a =& new foo();"); + }).toThrow( + "Parse Error : syntax error, unexpected 'new' (T_NEW) on line 1", + ); + }); + it("call result", () => { + expect(parser.parseEval("$a =& foo( &$b );")).toMatchSnapshot(); + }); + it("return statement", () => { + expect(parser.parseEval("return &$foo;")).toMatchSnapshot(); + }); + it("function definition", () => { + expect(parser.parseEval("function &foo( &$bar ) { }")).toMatchSnapshot(); + }); + it("variadic", () => { + expect(parser.parseEval("function test(&...$var) { }")).toMatchSnapshot(); + }); + it("foreach", () => { + expect(parser.parseEval("foreach ($arr as &$value) { }")).toMatchSnapshot(); + }); + it("foreach (key/value)", () => { + expect( + parser.parseEval("foreach ($arr as $key => &$val) { }"), + ).toMatchSnapshot(); + }); + it("closure", () => { + expect( + parser.parseEval("$var = function () use (&$message) { };"), + ).toMatchSnapshot(); + }); + // https://github.com/php/php-src/blob/php-7.4.0beta4/Zend/zend_language_parser.y#L1165 + it("callable variable", () => { + expect(parser.parseEval("$var = &$var;")).toMatchSnapshot(); + }); + it("callable variable #2", () => { + expect(parser.parseEval("$var = &${$var};")).toMatchSnapshot(); + }); + it("callable variable #3", () => { + expect(parser.parseEval("$var = &$$$var;")).toMatchSnapshot(); + }); + it("callable variable #4", () => { + expect(parser.parseEval("$var = &$var[$var];")).toMatchSnapshot(); + }); + it("callable variable #5", () => { + expect(parser.parseEval("$var = &CONSTANT[$var];")).toMatchSnapshot(); + }); + it("callable variable #6", () => { + expect(parser.parseEval("$var = &$var{$var}[$var];")).toMatchSnapshot(); + }); + it("callable variable #7", () => { + expect(parser.parseEval("$var = &$var->test();")).toMatchSnapshot(); + }); + it("callable variable #8", () => { + expect(parser.parseEval("$var = &call();")).toMatchSnapshot(); + }); + // https://github.com/php/php-src/blob/php-7.4.0beta4/Zend/zend_language_parser.y#L1167 + it("staticlookup", () => { + expect(parser.parseEval("$var = &Foo::$test;")).toMatchSnapshot(); + }); + it("staticlookup #2", () => { + expect(parser.parseEval("$var = &Foo::${$test};")).toMatchSnapshot(); + }); + it("staticlookup #3", () => { + expect(parser.parseEval("$var = &Foo::$$$test;")).toMatchSnapshot(); + }); + it("staticlookup #4", () => { + expect(parser.parseEval("$var = &$var::$test;")).toMatchSnapshot(); + }); + it("staticlookup #5", () => { + expect(parser.parseEval("$var = &$var::${$test};")).toMatchSnapshot(); + }); + it("staticlookup #6", () => { + expect(parser.parseEval("$var = &$var::$$$test;")).toMatchSnapshot(); + }); + it("staticlookup #7", () => { + expect( + parser.parseEval("$var = &parent::getElementByPath();"), + ).toMatchSnapshot(); + }); + it("staticlookup #8", () => { + expect( + parser.parseEval(" $var = &self::getElementByPath();"), + ).toMatchSnapshot(); + }); + // https://github.com/php/php-src/blob/php-7.4.0beta4/Zend/zend_language_parser.y#L1169 + it("propertylookup", () => { + expect(parser.parseEval("$var = &$var->test;")).toMatchSnapshot(); + }); + it.skip("propertylookup #2", () => { + expect(parser.parseEval("$var = &($var)->test;")).toMatchSnapshot(); + }); + it("with bin", () => { + expect(parser.parseEval("$foo = &$bar || $bar;")).toMatchSnapshot(); + }); + it("with bin #2", () => { + expect(parser.parseEval("$foo = &$bar + 1;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/call.test.js b/test/snapshot/call.test.js new file mode 100644 index 000000000..0ab555383 --- /dev/null +++ b/test/snapshot/call.test.js @@ -0,0 +1,315 @@ +const parser = require("../main"); + +describe("Test call", function () { + it("simple", function () { + const ast = parser.parseEval("call();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("multiple", function () { + const ast = parser.parseEval("call()()();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("multiple (2)", function () { + const ast = parser.parseEval("$obj->call()->call()->call();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("nested", function () { + const ast = parser.parseEval("call(call(call()));", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("single argument", function () { + const ast = parser.parseEval("call($a);", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("multiple arguments", function () { + const ast = parser.parseEval("call($a, $b, $c);", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("propertylookup", function () { + const ast = parser.parseEval("$obj->call();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("propertylookup (2)", function () { + const ast = parser.parseEval("$obj->property->call();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("nullsafepropertylookup", function () { + const ast = parser.parseEval("$obj?->call();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("nullsafepropertylookup (2)", function () { + const ast = parser.parseEval("$obj?->property?->call();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("staticlookup", function () { + const ast = parser.parseEval("$obj::call();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("staticlookup (2)", function () { + const ast = parser.parseEval("Foo::call();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("offsetlookup", function () { + const ast = parser.parseEval('$array["index"]();', { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("parent", function () { + const ast = parser.parseEval( + "class Foo { function foo() { parent::call(); } }", + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + it("self", function () { + const ast = parser.parseEval( + "class Foo { function foo() { self::call(); } }", + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + it("static", function () { + const ast = parser.parseEval( + "class Foo { function foo() { static::call(); } }", + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + it("variable function", function () { + const ast = parser.parseEval("$func();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("variable function (2)", function () { + const ast = parser.parseEval("$obj->$func();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("variable function (3)", function () { + const ast = parser.parseEval("Foo::$func();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("string", function () { + const ast = parser.parseEval('("func")();', { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("array", function () { + const ast = parser.parseEval('array("Foo", "bar")();', { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("array parens", function () { + const ast = parser.parseEval('(array("Foo", "bar"))();', { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside offsetlookup", function () { + const ast = parser.parseEval('get_class($obj)["offset"];', { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside propertylookup", function () { + const ast = parser.parseEval("get_class($obj)->property;", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup", function () { + const ast = parser.parseEval("get_class($obj)::call();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup (2)", function () { + const ast = parser.parseEval("get_class($obj)::call()::call()::call();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup (3)", function () { + const ast = parser.parseEval("get_class($obj)::$property;", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup (4)", function () { + const ast = parser.parseEval( + "get_class($obj)::$property::$property::$property;", + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup (5)", function () { + const ast = parser.parseEval("get_class($obj)::CONSTANT;", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup (6)", function () { + const ast = parser.parseEval("get_class($var)::${$property};", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup (7)", function () { + const ast = parser.parseEval( + "get_class($var)::${$property}::${$property}::${$property};", + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup (8)", function () { + const ast = parser.parseEval('get_class($var)::${"property"};', { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup (9)", function () { + const ast = parser.parseEval("get_class($var)::${$property};", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup (10)", function () { + const ast = parser.parseEval("Order::call()();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("inside staticlookup (11)", function () { + const ast = parser.parseEval("Order::{call()}();", { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("trailing comma", function () { + const ast = parser.parseEval('foo("method", "bar",);', { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("trailing comma #2", function () { + const ast = parser.parseEval('$foo("method", "bar",);', { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("trailing comma #3", function () { + const ast = parser.parseEval('$foo->bar("method", "bar",);', { + parser: { debug: false }, + }); + expect(ast).toMatchSnapshot(); + }); + it("named arguments in php 8.0", function () { + const astErr = parser.parseEval(`foo(a: $a);`, { + parser: { + version: "8.0", + debug: false, + }, + }); + expect(astErr).toMatchSnapshot(); + }); + it("named arguments are not supported in php 7.2", function () { + expect(() => + parser.parseEval(`foo(a: $a);`, { + parser: { + version: "7.2", + debug: false, + }, + }), + ).toThrow("PHP 8+ is required to use named arguments"); + }); + it("doesnt confused static methods with named arguments", function () { + const astErr = parser.parseEval(`foo(a::bar());`, { + parser: { + version: "8.0", + debug: false, + }, + }); + expect(astErr).toMatchSnapshot(); + }); + it("keyword as named argument", function () { + const astErr = parser.parseEval(`foo(array: $a);`, { + parser: { + version: "8.0", + debug: false, + }, + }); + expect(astErr).toMatchSnapshot(); + }); + it("mix of unnamed and named arguments", function () { + const astErr = parser.parseEval(`foo(50, num: 100, start_index: 0);`, { + parser: { + version: "8.0", + debug: false, + }, + }); + expect(astErr).toMatchSnapshot(); + }); + it("comments", function () { + const astErr = parser.parseEval( + `foo(array // comment + (100, 0));`, + { + parser: { + extractDoc: true, + debug: false, + }, + }, + ); + expect(astErr).toMatchSnapshot(); + }); + it("handles spread operator at call site", function () { + expect( + parser.parseEval(` + foo(...$bar); + foo($bar, ...$baz); + foo(...$bar, ...$baz); + `), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/class.test.js b/test/snapshot/class.test.js new file mode 100644 index 000000000..ac0d31a0d --- /dev/null +++ b/test/snapshot/class.test.js @@ -0,0 +1,308 @@ +const parser = require("../main"); + +describe("Test classes", function () { + it("Implement #183 : static keyword as identifier", function () { + expect( + parser.parseEval(` + class A { + public static function test() { + parent::foo(); + self::bar(); + static::baz(); + A::fooBar(); + $this->fooBaz(); + } + } + `), + ).toMatchSnapshot(); + }); + + it("Implement typed_properties_v2 / php74", function () { + expect( + parser.parseEval(` + class Test { + public ?int $prop = null; + protected static float|string $y; + } + `), + ).toMatchSnapshot(); + }); + + it("Implement readonly property", function () { + expect( + parser.parseEval( + ` + class User { + public readonly int $uid; + } + `, + { + parser: { + version: "8.1", + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("Validate usual declarations", function () { + expect( + parser.parseEval(` + final class foo extends bar implements + bim, bam, boum { + const FOO = "azerty"; + public static $var; + public function __construct(array $data = null) { + $this->data = $data; + } + const list = "bar"; + public function new($foo = self::list) { + return $this::list; + } + protected $foo; + private $bar; + function foobar() {} + } + abstract class bar { + use A, B { + B::smallTalk insteadof A; + A::bigTalk insteadof B, C; + B::bigTalk as public talk; + B::bigTalk as protected talk; + B::bigTalk as private talk; + A::new as list; + list as new; + } + /** + * Some informations + */ + abstract protected function &foo() : bar; + }`), + ).toMatchSnapshot(); + }); + + it("Advanced tests", function () { + expect( + parser.parseEval( + ` + class foo implements boo { + use A; + use B { foo as bar; } + // comment + /* boo */ + /** doc + * data + foo + */ + var $var = true; + final function __construct() { } + private function boo() { } + } + interface boo extends something { + // some doc + const A = 1.5; + /** foo */ + protected function foo(); + } + trait line { + // some doc + const A = 1.5; + abstract protected function foo(); + } + `, + { + parser: { extractDoc: true }, + }, + ), + ).toMatchSnapshot(); + }); + + it("Test of silent mode", function () { + expect( + parser.parseEval( + ` + class foo { + use A + use B { foo }; + }`, + { + parser: { suppressErrors: true }, + }, + ), + ).toMatchSnapshot(); + }); + + it("Test js properties", function () { + expect( + parser.parseEval(` + class __proto__ { + static $constructor; + public function constructor() {} + public function __proto__() { + $this->constructor = null; + self::$constructor = null; + } + }`), + ).toMatchSnapshot(); + }); + + it("Test promoted class properties php 8", function () { + const ast = parser.parseEval( + ` + class __proto__ { + public function constructor(public int $id, private $name, int $c, protected ServerRequestInterface $req) {} + }`, + { + parser: { + version: "8.0", + suppressErrors: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("Test promoted readonly class properties", function () { + const ast = parser.parseEval( + ` + class Bob { + public function __construct(public readonly int $id) {} + } + class Bob2 { + public function __construct(readonly public int $id) {} + } +`, + { + parser: { + version: "8.1", + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("Test that readonly method parameters are throwing errors", function () { + const ast = parser.parseEval( + ` + class Bob { + public function foo(public readonly int $id) {} + }`, + { + parser: { + version: "8.1", + suppressErrors: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("Test promoted nullable properties php 8", function () { + const ast = parser.parseEval( + ` + class __proto__ { + public function constructor(public ?string $maybe, private ?int $opt) {} + }`, + { + parser: { + version: "8.0", + suppressErrors: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + describe("readonly class in PHP8.2", function () { + [ + "readonly", + "readonly abstract", + "abstract readonly", + "final readonly", + "readonly final", + ].forEach(function (token) { + it("should support " + token, function () { + expect( + parser.parseEval(` + ${token} class Foo { + } + `), + ).toMatchSnapshot(); + }); + }); + }); + + it("empty", function () { + expect(parser.parseEval("class Foo {}")).toMatchSnapshot(); + }); + + it("class name as identifier", function () { + expect(parser.parseEval("class A {}")).toMatchSnapshot(); + }); + + it("final and abstract", function () { + expect( + parser.parseEval(`final abstract class foo {}`, { + parser: { suppressErrors: true }, + }), + ).toMatchSnapshot(); + }); + + it("abstract and final", function () { + expect( + parser.parseEval(`abstract final class foo {}`, { + parser: { suppressErrors: true }, + }), + ).toMatchSnapshot(); + }); + + it("8.4 allow new without parenthesis", () => { + const code = `new People()->name();`; + const test_parser = parser.create({ + parser: { + version: "8.4", + }, + }); + expect(test_parser.parseEval(code)).toMatchSnapshot(); + }); + + it("new without parenthesis throw errors in PHP < 8.4", () => { + const code = `new People()->name();`; + expect(() => { + parser.parseEval(code); + }).toThrowErrorMatchingSnapshot(); + }); + + it("knows where a function definiton starts", function () { + const phpCode = ` +class b { + // prettier-ignore + public static function a() {} +} + `; + const ast = parser.parseEval(phpCode, { + ast: { + withPositions: true, + withSource: true, + }, + }); + const funcStart = ast.children[0].body[0].loc.start.offset; + const funcEnd = ast.children[0].body[0].loc.end.offset; + expect(phpCode.substr(funcStart, funcEnd - funcStart)).toEqual( + "public static function a() {}", + ); + expect(ast.children[0].body[0].loc.source).toEqual( + "public static function a()", + ); + }); + + it("handles property types with a leading \\", function () { + expect( + parser.parseEval(` + class Foo { + public \\Bar $baz; + } + `), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/classconstant.test.js b/test/snapshot/classconstant.test.js new file mode 100644 index 000000000..287845a7d --- /dev/null +++ b/test/snapshot/classconstant.test.js @@ -0,0 +1,78 @@ +const parser = require("../main"); + +describe("classconstant", () => { + it("simple", () => { + expect( + parser.parseEval('class Foo { const CONSTANT = "Hello world!"; }'), + ).toMatchSnapshot(); + }); + it("simple using 8.3", () => { + expect( + parser.parseEval(`class Foo { const CONSTANT = "Hello world!"; }`, { + parser: { version: 803 }, + }), + ).toMatchSnapshot(); + }); + + it("multiple", () => { + expect( + parser.parseEval( + 'class Foo { const CONSTANT = "Hello world!", OTHER_CONSTANT = "Other hello world!"; }', + ), + ).toMatchSnapshot(); + }); + + it("multiple 8.3", () => { + expect( + parser.parseEval( + 'class Foo { const NAME_1 = "Hello world!", NAME_2 = "Other hello world!"; }', + { + parser: { version: 803 }, + }, + ), + ).toMatchSnapshot(); + }); + + it("public", () => { + expect( + parser.parseEval('class Foo { public const CONSTANT = "Hello world!"; }'), + ).toMatchSnapshot(); + }); + it("protected", () => { + expect( + parser.parseEval( + 'class Foo { protected const CONSTANT = "Hello world!"; }', + ), + ).toMatchSnapshot(); + }); + it("private", () => { + expect( + parser.parseEval( + 'class Foo { private const CONSTANT = "Hello world!"; }', + ), + ).toMatchSnapshot(); + }); + it("final", () => { + expect( + parser.parseEval( + 'class Foo { final public const CONSTANT = "Hello world!"; }', + ), + ).toMatchSnapshot(); + }); + it("type hinted (supported)", () => { + expect( + parser.parseEval( + 'class Foo { public const string CONSTANT = "Hello world!"; }', + { parser: { version: 803 } }, + ), + ).toMatchSnapshot(); + }); + it("type hinted (unsupported)", () => { + expect(() => + parser.parseEval( + 'class Foo { public const string CONSTANT = "Hello world!"; }', + { parser: { version: 802 } }, + ), + ).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/snapshot/classreference.test.js b/test/snapshot/classreference.test.js new file mode 100644 index 000000000..c4687e687 --- /dev/null +++ b/test/snapshot/classreference.test.js @@ -0,0 +1,21 @@ +const parser = require("../main"); + +describe("classreference", function () { + it("variable", function () { + expect(parser.parseEval("Foo::$var;")).toMatchSnapshot(); + }); + it("constant", function () { + expect(parser.parseEval("Foo::CONSTANT;")).toMatchSnapshot(); + }); + it("call", function () { + expect(parser.parseEval("Foo::call();")).toMatchSnapshot(); + }); + it("argument type", function () { + expect(parser.parseEval("function foo(Foo $arg) {}")).toMatchSnapshot(); + }); + it("argument type (2)", function () { + expect( + parser.parseEval("function foo(Foo\\Foo $arg) {}"), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/clone.test.js b/test/snapshot/clone.test.js new file mode 100644 index 000000000..90ad67d49 --- /dev/null +++ b/test/snapshot/clone.test.js @@ -0,0 +1,10 @@ +const parser = require("../main"); + +describe("clone", function () { + it("simple", function () { + expect(parser.parseEval("clone $obj;")).toMatchSnapshot(); + }); + it("assign", function () { + expect(parser.parseEval("$var = clone $obj;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/closure.test.js b/test/snapshot/closure.test.js new file mode 100644 index 000000000..5dfa6395f --- /dev/null +++ b/test/snapshot/closure.test.js @@ -0,0 +1,69 @@ +const parser = require("../main"); + +describe("closure", () => { + it("simple", () => { + expect( + parser.parseEval('$var = function() { echo "something"; };'), + ).toMatchSnapshot(); + }); + it("empty", () => { + expect(parser.parseEval("$var = function() {};")).toMatchSnapshot(); + }); + it("argument", () => { + expect( + parser.parseEval('$var = function($arg) { echo "something"; };'), + ).toMatchSnapshot(); + }); + it("argument by ref", () => { + expect( + parser.parseEval('$var = function(&$arg) { echo "something"; };'), + ).toMatchSnapshot(); + }); + it("arguments", () => { + expect( + parser.parseEval( + '$var = function($arg, $arg, $arg) { echo "something"; };', + ), + ).toMatchSnapshot(); + }); + it("use", () => { + expect( + parser.parseEval( + '$var = function() use ($message) { echo "something"; };', + ), + ).toMatchSnapshot(); + }); + it("use multiple", () => { + expect( + parser.parseEval( + '$var = function() use ($message, $message1, $message2) { echo "something"; };', + ), + ).toMatchSnapshot(); + }); + it("use by ref", () => { + expect( + parser.parseEval( + '$var = function() use (&$message) { echo "something"; };', + ), + ).toMatchSnapshot(); + }); + it("argument and use", () => { + expect( + parser.parseEval( + '$var = function($arg) use ($use) { echo "something"; };', + ), + ).toMatchSnapshot(); + }); + it("arguments and uses", () => { + expect( + parser.parseEval( + '$var = function($arg, $arg, $arg) use ($use, $use, $use) { echo "something"; };', + ), + ).toMatchSnapshot(); + }); + it("inside call", () => { + expect( + parser.parseEval(`call(function ($arg) { return $arg; });`), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/comment.test.js b/test/snapshot/comment.test.js new file mode 100644 index 000000000..a20ddf4d6 --- /dev/null +++ b/test/snapshot/comment.test.js @@ -0,0 +1,299 @@ +const parser = require("../main"); + +describe("Test comments", function () { + describe("issues", function () { + it("fix #250 : Leading comments are treated as trailing comments", function () { + expect( + parser.parseEval( + ` +// leading +foo(); +// bar +bar() /* inner */ ; +// trailing + `, + { + parser: { + extractDoc: true, + // debug: true + }, + ast: { + withPositions: true, + withSource: true, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("fix call comments", function () { + expect( + parser.parseEval( + ` +call(array // comment +()); + `, + { + parser: { + extractDoc: true, + // debug: true + }, + ast: { + withPositions: true, + withSource: true, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("fix #126 : new option", function () { + const ast = parser.parseEval( + ` + if (true) { + $a = 1; + } + // Don't parsed :( + else if (false) { + $a = 2 /* trailing 2 */ ; + // trailing assing + } + // trailing elseif + `, + { + parser: { + extractDoc: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + it("fix #55", function () { + const ast = parser.parseEval( + ` + if (true): + if (true): + // inner statements + endif; // another comment + endif; // 2nd comment + `, + { + parser: { + extractDoc: true, + // debug: true + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("fix #189", function () { + const ast = parser.parseEval( + ` + $var = 'string1' + // Comment 1 + . 'string2' // Comment 2 + // Comment 3 + . 'string3'; + `, + { + parser: { + extractDoc: true, + // debug: true + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("fix #193", function () { + const ast = parser.parseEval( + ` + $a = $var + // Comment Before + -> + // Comment After + each(); + `, + { + parser: { + extractDoc: true, + // debug: true + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("fix #278", function () { + const ast = parser.parseEval( + ` +/** + * Class description + */ +class FooClass +{ + /** + * Description + */ + public static function bar() + { + return $array; + } + + /** + * Description + */ + public static function baz() + { + return $array; + } + + /** + * Description + */ + public static function woo() + { + return $array; + } + // true trailing comment +} + `, + { + parser: { + extractDoc: true, + // debug: true + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("impl #194", function () { + const ast = parser.parseEval( + ` + // lead assign + $foo /* trail foo */ = /* lead 1 */ 1 /* trail 1 */; + // lead call + callback(/* lead arg */ "arg" /* trail arg */ ) /* trail call */ ; + /* trail program */ + `, + { + parser: { + extractDoc: true, + // debug: true + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + }); + + it("test single line comments", function () { + const ast = parser.parseEval( + ` + # some information + // another line + $foo = 123 // 123 + ; /* done */ + `, + { + parser: { + extractDoc: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + describe("multi line comments", function () { + it("test function", function () { + const ast = parser.parseEval( + ` + /** + * Description + */ + function /* ignore */ & /* ignore */ name(/* @var something */ $arg) { + // inner + return $arg /* ignore */; + } + `, + { + parser: { + extractDoc: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + it("test if statements", function () { + const ast = parser.parseEval( + ` + if /* ignore */ (/* */ true) /* ignore */ { + # inner statement + } /* ignore */ else /* ignore */ + // else with a inner if single statement : + if (true /* ignore */) /* ignore */ { + } /* ignore */ elseif /* ignore */ (/* ignore */ false /* ignore */ /* ignore */) /* ignore */ /* ignore */ { + } /* ignore */ else /* ignore */ { + } + if (false) /* ignore */ : /* ignore */ + /* ignore */ endif /* ignore */;/* ignore */ + `, + { + parser: { + extractDoc: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + it("test try statements", function () { + const ast = parser.parseEval( + ` + try /* ignore */ { + # inner statement + } /* dd */ catch(/* zz */ \\Exception /* 1 */ | /* 2 */ \\Foo /* aa */ $e /* bb */) /* dd */ { + /* ee */ + } /* zz */ finally /* yy */ { + /* ignore */ + } // end + `, + { + parser: { + extractDoc: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + }); + + it("test classes", function () { + const ast = parser.parseEval( + ` + /** + * Description + */ + class /* ignore */ name /* hehe */ { + // @var test + protected $test, $toto; + // ignored comment + /** @var Class */ + static public $foo = 123; + /** ignored also **/ + /** + * @return void + */ + public function void() { } + } + `, + { + parser: { + extractDoc: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/constantstatement.test.js b/test/snapshot/constantstatement.test.js new file mode 100644 index 000000000..f7d9718ec --- /dev/null +++ b/test/snapshot/constantstatement.test.js @@ -0,0 +1,16 @@ +const parser = require("../main"); + +describe("constantstatement", () => { + it("simple", () => { + expect( + parser.parseEval('const CONSTANT = "Hello world!";'), + ).toMatchSnapshot(); + }); + it("multiple", () => { + expect( + parser.parseEval( + 'const CONSTANT = "Hello world!", OTHER_CONSTANT = "Other hello world!";', + ), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/continue.test.js b/test/snapshot/continue.test.js new file mode 100644 index 000000000..39ea5e648 --- /dev/null +++ b/test/snapshot/continue.test.js @@ -0,0 +1,30 @@ +const parser = require("../main"); + +describe("continue", () => { + it("simple", () => { + expect(parser.parseEval("continue;")).toMatchSnapshot(); + }); + it("argument 0", () => { + expect(parser.parseEval("continue 0;")).toMatchSnapshot(); + }); + it("argument 1", () => { + expect(parser.parseEval("continue 1;")).toMatchSnapshot(); + }); + it("argument 2", () => { + expect(parser.parseEval("continue 2;")).toMatchSnapshot(); + }); + it("with parens", () => { + expect(parser.parseEval("continue (1);")).toMatchSnapshot(); + }); + // Deprecated since 5.4.0 + it("with expression", () => { + expect(parser.parseEval("continue $var;")).toMatchSnapshot(); + }); + it("should fail when no ';' at end", function () { + expect( + parser.parseEval("continue", { + parser: { suppressErrors: true }, + }), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/declare.test.js b/test/snapshot/declare.test.js new file mode 100644 index 000000000..5c4808532 --- /dev/null +++ b/test/snapshot/declare.test.js @@ -0,0 +1,26 @@ +const parser = require("../main"); + +describe("declare", function () { + it("strict_types", function () { + expect(parser.parseEval("declare (strict_types=1);")).toMatchSnapshot(); + }); + it("ticks", function () { + expect(parser.parseEval("declare(ticks=1);")).toMatchSnapshot(); + }); + it("encoding", function () { + expect( + parser.parseEval("declare(encoding='ISO-8859-1');"), + ).toMatchSnapshot(); + }); + it("nested", function () { + expect(parser.parseEval("declare(ticks=1) { }")).toMatchSnapshot(); + }); + it("mode short", function () { + expect( + parser.parseEval('declare(ticks=1): echo "something"; enddeclare;'), + ).toMatchSnapshot(); + }); + it("multiple", function () { + expect(parser.parseEval("declare (A='B', C='D') { }")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/echo.test.js b/test/snapshot/echo.test.js new file mode 100644 index 000000000..0de2397e0 --- /dev/null +++ b/test/snapshot/echo.test.js @@ -0,0 +1,10 @@ +const parser = require("../main"); + +describe("echo", function () { + it("simple", function () { + expect(parser.parseEval('echo "string";')).toMatchSnapshot(); + }); + it("multiple", function () { + expect(parser.parseEval('echo "string", "string";')).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/empty.test.js b/test/snapshot/empty.test.js new file mode 100644 index 000000000..8d1d67f8b --- /dev/null +++ b/test/snapshot/empty.test.js @@ -0,0 +1,10 @@ +const parser = require("../main"); + +describe("empty", function () { + it("simple", function () { + expect(parser.parseEval("empty($var);")).toMatchSnapshot(); + }); + it("assign", function () { + expect(parser.parseEval("$var = empty($var);")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/encapsed.test.js b/test/snapshot/encapsed.test.js new file mode 100644 index 000000000..3e95f60e4 --- /dev/null +++ b/test/snapshot/encapsed.test.js @@ -0,0 +1,132 @@ +const parser = require("../main"); + +describe("encapsed", function () { + it.each([ + ["variable (simple syntax)", '"string $var string";'], + ["two variable (simple syntax)", '"string $var->$var string";'], + ["variable curly (simple syntax)", '"string ${var} string";'], + ["offsetlookup (simple syntax)", '"string $array[0] string";'], + ["offsetlookup (2) (simple syntax)", '"string $array[koolaid1] string";'], + ["offsetlookup (3) (simple syntax)", '"string $array[0][0] string";'], + ["propertylookup (simple syntax)", '"string $obj->property string";'], + [ + "nullsafepropertylookup (simple syntax)", + '"string $obj?->property string";', + ], + ["variable with space opening before curly", '"string { $var} string";'], + ["variable with before closing curly", '"string {$var } string";'], + ["variable (complex syntax)", '"string {$var} string";'], + ["propertylookup (complex syntax)", '"string {$obj->property} string";'], + [ + "nullsafepropertylookup (complex syntax)", + '"string {$obj?->property} string";', + ], + ["offsetlookup (complex syntax)", '"string {$array["key"]} string";'], + ["offsetlookup 2 (complex syntax)", '"string {$array[4][3]} string";'], + ["offsetlookup 3 (complex syntax)", '"string {$arr[foo][3]} string";'], + ["offsetlookup 4 (complex syntax)", '"string {$arr["foo"][3]} string";'], + [ + "nullsafepropertylookup and offsetlookup (complex syntax)", + '"string {$obj?->values[3]?->name} string";', + ], + ["value of the var (complex syntax)", '"string {${$name}} string";'], + [ + "value of the var named by the return value (complex syntax)", + '"string {${call()}} string";', + ], + [ + "value of the var named by the return value (2) (complex syntax)", + '"string {${call()}} string";', + ], + [ + "value of the var named by the return value (3) (complex syntax)", + '"string {${$obj->property}} string";', + ], + [ + "value of the var named by the return value (4) (complex syntax)", + '"string {${$obj->call()}} string";', + ], + [ + "value of the var named by the return value (5) (complex syntax)", + '"string {${$obj::$var}} string";', + ], + [ + "value of the var named by the return value (6) (complex syntax)", + '"string {${$obj::call()}} string";', + ], + [ + "propertylookup by variable (complex syntax)", + '"string {$obj->$var} string";', + ], + [ + "nullsafepropertylookup by variable (complex syntax)", + '"string {$obj?->$var} string";', + ], + [ + "propertylookup by variable (2) (complex syntax)", + '"string {$obj->{$array[1]}} string";', + ], + [ + "nullsafepropertylookup by variable (2) (complex syntax)", + '"string {$obj?->{$array[1]}} string";', + ], + [ + "propertylookup with multiple call (complex syntax)", + '"string {$obj->call()->call()} string";', + ], + [ + "nullsafepropertylookup with multiple call (complex syntax)", + '"string {$obj?->call()?->call()} string";', + ], + [ + "multiple propertylookup (complex syntax)", + '"string {$obj->property->property} string";', + ], + [ + "multiple nullsafepropertylookup (complex syntax)", + '"string {$obj?->property?->property} string";', + ], + [ + "propertylookup with comments (complex syntax)", + '"string {$var->foo->bar /* Comment */ } string";', + ], + [ + "nullsafepropertylookup with comments (complex syntax)", + '"string {$var?->foo?->bar /* Comment */ } string";', + ], + [ + "newline before closing curly (complex syntax)", + '"string {$var\n} string";', + ], + ["staticlookup (complex syntax)", '"string {$obj::$var} string";'], + ["staticlookup (2) (complex syntax)", '"string {$obj::call()} string";'], + [ + "staticlookup (3) (complex syntax)", + '"string {$obj::$var::$var} string";', + ], + [ + "staticlookup (4) (complex syntax)", + '"string {$var::$target::$resource::$binary::$foo::$bar::$foobar::$bar::$foo::$foobar::$bar::$foo} string";', + ], + ["string offset in encapsed var offset", `"$var[var]";`], + ["positive offset in encapsed var offset", `"$var[1]";`], + ["negative offset in encapsed var offset", `"$var[-1]";`], + ["string offset in encapsed var offset", `"$var[$var]";`], + ["dollar open curly braces", '"string ${juice} string";'], + ["dollar open curly braces #2", '"string ${$juice} string";'], + ["dollar open curly braces #3", '"string ${${$juice}} string";'], + ["dollar open curly braces #4", '"string ${call()} string";'], + ["dollar open curly braces #5", '"string ${test[test]} string";'], + ["dollar open curly braces #6", '"string ${test[1]} string";'], + ["dollar open curly braces #7", '"string ${test[-1]} string";'], + ["dollar open curly braces #8", '"string ${test[$var]} string";'], + ["curly", '"string {$juice} string";'], + ["curly #2", '"string {$$juice} string";'], + ["curly #3", '"string {$call()} string";'], + ["no curly", '"string $$juice string";'], + ["propertylookup", '$this->{"set{$type}"};'], + ["nullsafepropertylookup", '$this?->{"set{$type}"};'], + ])("%s", function (_, code) { + expect(parser.parseEval(code)).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/enum.test.js b/test/snapshot/enum.test.js new file mode 100644 index 000000000..8b3c1a8e8 --- /dev/null +++ b/test/snapshot/enum.test.js @@ -0,0 +1,114 @@ +const parser = require("../main"); + +describe("Test enums", function () { + it("empty", function () { + expect(parser.parseEval("enum Foo {}")).toMatchSnapshot(); + }); + + it("non-empty", function () { + expect( + parser.parseEval(` + enum Suit { + case Hearts; + case Diamonds; + case Clubs; + case Spades; + } + `), + ).toMatchSnapshot(); + }); + + it("may have a backing type", function () { + expect( + parser.parseEval(` + enum Suit: string { + case Hearts = 'H'; + case Diamonds = 'D'; + case Clubs = 'C'; + case Spades = 'S'; + } + `), + ).toMatchSnapshot(); + }); + + it("can alias cases", function () { + expect( + parser.parseEval(` + enum Foo { + case Bar; + public const Baz = self::Bar; + } + `), + ).toMatchSnapshot(); + }); + + it("can implement interfaces", function () { + expect( + parser.parseEval(` + enum Foo implements Bar, Baz {} + `), + ).toMatchSnapshot(); + }); + + it("can use traits", function () { + expect( + parser.parseEval(` + enum Foo { + use Bar, Baz { + Baz::hello insteadof Bar; + Baz::world as earth; + } + use Bax; + } + `), + ).toMatchSnapshot(); + }); + + it("can have functions", function () { + expect( + parser.parseEval(` + enum Foo: int { + case MyCase = 1; + + public function bar(): void {} + + protected static function baz() { + echo self::MyCase->value; + } + } + `), + ).toMatchSnapshot(); + }); + + it("cannot have properties", function () { + expect(() => { + parser.parseEval(` + enum Foo { + public int $bar; + protected $baz; + } + `); + }).toThrowErrorMatchingSnapshot(); + }); + + it("doesn't confuse enums with identifiers", function () { + expect( + parser.parseEval(` + class Enum { function enum () {} } + interface Enum {} + trait Enum {} + function enum() {} + class Enum extends Foo {} + class Enum implements Foo {} + class Enum exTends Foo {} + enum extendsFoo {} + `), + ).toMatchSnapshot(); + }); + + it("can't be parsed with PHP < 8", function () { + expect(() => { + parser.parseEval("enum Foo {}", { parser: { version: "8.0" } }); + }).toThrowErrorMatchingSnapshot(); + }); +}); diff --git a/test/snapshot/eval.test.js b/test/snapshot/eval.test.js new file mode 100644 index 000000000..0dfe526df --- /dev/null +++ b/test/snapshot/eval.test.js @@ -0,0 +1,7 @@ +const parser = require("../main"); + +describe("eval", function () { + it("simple", function () { + expect(parser.parseEval('eval("command");')).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/exit.test.js b/test/snapshot/exit.test.js new file mode 100644 index 000000000..deb8a21d1 --- /dev/null +++ b/test/snapshot/exit.test.js @@ -0,0 +1,31 @@ +const parser = require("../main"); + +describe("exit", function () { + it("simple", function () { + expect(parser.parseEval("exit();")).toMatchSnapshot(); + }); + it("argument", function () { + expect(parser.parseEval("exit($var);")).toMatchSnapshot(); + }); + it("die", function () { + expect(parser.parseEval("die();")).toMatchSnapshot(); + }); + it("exit without expression", function () { + expect(parser.parseEval("exit;")).toMatchSnapshot(); + }); + it("exit with empty expression", function () { + expect(parser.parseEval("exit();")).toMatchSnapshot(); + }); + it("exit with expression", function () { + expect(parser.parseEval("exit(10 + $var);")).toMatchSnapshot(); + }); + it("die without expression", function () { + expect(parser.parseEval("die;")).toMatchSnapshot(); + }); + it("die with empty expression", function () { + expect(parser.parseEval("die();")).toMatchSnapshot(); + }); + it("die with expression", function () { + expect(parser.parseEval("die(10 + $var);")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/expr.test.js b/test/snapshot/expr.test.js new file mode 100644 index 000000000..89dcb2b41 --- /dev/null +++ b/test/snapshot/expr.test.js @@ -0,0 +1,313 @@ +const parser = require("../main"); + +describe("Test expressions", function () { + it("test binary", function () { + const ast = parser.parseEval( + ` + 1 | 3; + 1 & 3; + 1 ^ 3; + "1" . "3"; + 1 + 3; + 1 - 3; + 1 * 3; + 1 / 3; + 1 % 3; + 1 ** 3; + 1 << 3; + 1 >> 3; + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test more binary ops (formerly bool)", function () { + const ast = parser.parseEval( + ` + $a && $b; + $a AND $b; + $a || $b; + $a OR $b; + $a XOR $b; + $a === $b; + $a !== $b; + $a == $b; + $a != $b; + $a > $b; + $a < $b; + $a >= $b; + $a <= $b; + $a <=> $b; + $a instanceof $b; + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test assignements", function () { + const ast = parser.parseEval( + ` + $a = $b; + $a .= $b; + $a += $b; + $a -= $b; + $a *= $b; + $a **= $b; + $a /= $b; + $a &= $b; + $a |= $b; + $a %= $b; + $a ^= $b; + $a <<= $b; + $a >>= $b; + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test if based returns", function () { + const ast = parser.parseEval( + ` + $a ?? false; + $a > 5 ? true : false; + $a ?: false; + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test silent", function () { + const ast = parser.parseEval("@trigger_error();"); + expect(ast).toMatchSnapshot(); + }); + + it("test generators", function () { + const ast = parser.parseEval( + ` + function gen() { + yield 0; // key 0 + yield from foo(); // keys 0-2 + yield 1 => $a; // key 1 + } + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test unary", function () { + const ast = parser.parseEval( + ` + +$var; + ~$var; + !$var; + -$var; + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test cast", function () { + const ast = parser.parseEval( + ` + (int)$var; + (integer)$var; + (bool)$var; + (boolean)$var; + (float)$var; + (double)$var; + (real)$var; + (string)$var; + (binary)$var; + (array)$var; + (object)$var; + (unset)$var; + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test cast extension - #171", function () { + const ast = parser.parseEval( + ` + (int)$var; + (integer)$var; + (bool)$var; + (boolean)$var; + (float)$var; + (double)$var; + (real)$var; + (string)$var; + (binary)$var; + (array)$var; + (object)$var; + (unset)$var; + `, + { + parser: { + read_expr_cast: function (cast) { + const rawCast = this.text(); + const expr = this.next().read_expr(); + expr.cast = cast; + expr.rawCast = rawCast; + return expr; + }, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test exit", function () { + const ast = parser.parseEval( + ` + exit(1); + die(); + exit; + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test incr/decr", function () { + const ast = parser.parseEval( + ` + $i++; + $i--; + ++$i; + --$i; + `, + { + ast: { + withPositions: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("should fail to assign constants", function () { + const ast = parser.parseEval("a = 1;", { + parser: { debug: false, suppressErrors: true }, + }); + expect(ast).toMatchSnapshot(); + }); + + it("should fail to assign class constants", function () { + const ast = parser.parseEval("foo::b = 1;", { + parser: { debug: false, suppressErrors: true }, + }); + expect(ast).toMatchSnapshot(); + }); + + it("should assign class static", function () { + const ast = parser.parseEval("a::$b = 1;", { + parser: { debug: false, suppressErrors: true }, + }); + expect(ast).toMatchSnapshot(); + }); + + it("test new", function () { + const ast = parser.parseEval( + ` + $a = new \\foo(); + $a = new namespace\\foo::class(); + $a = new $foo(); + $a = new class extends foo implements bar { }; + `, + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("fix #234", function () { + expect( + parser.parseEval( + ` + new foo; + $a = (new foo)[0]; + `, + { parser: { debug: false } }, + ), + ).toMatchSnapshot(); + }); + + it("fix #235", function () { + expect( + parser.parseEval( + ` + self(); + sElF(); + parent(); + pArEnT(); + parent::foo(); + new self(); + new static(); + new parent(); + `, + { parser: { debug: false } }, + ), + ).toMatchSnapshot(); + }); + + it("test node references", function () { + expect( + parser.parseEval( + ` + parent::foo(); + new self(); + new static(); + new parent(); + `, + { parser: { debug: false } }, + ), + ).toMatchSnapshot(); + }); + + it("test fail new", function () { + expect( + parser.parseEval( + ` + $a = new foo[0]; + `, + { parser: { suppressErrors: true } }, + ), + ).toMatchSnapshot(); + }); + + it("test nested expressions precedence", function () { + const ast = parser.parseEval( + ` + $a = 5 * 2 + 1; // same as ((5 * 2) + 1) + $b = 5 * (2 + 1); + $c = 1 + 2 / 3 + 4; // same as (1 + ((2 / 3) + 4)) + $d = 1 !== 2 && 3; // same as (1 !== 2) && 3 + `, + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("chaining calls (derefenceable)", function () { + expect( + parser.parseEval(`($a->b)::call()->foo[10]->bar;`), + ).toMatchSnapshot(); + expect(parser.parseEval(`array(1, 2, 3)[0]->foo;`)).toMatchSnapshot(); + expect( + parser.parseEval(`($a++)($foo)->bar{$baz}::foo();`), + ).toMatchSnapshot(); + // expect error : + expect( + parser.parseEval(`($a++)bar::foo::baz;`, { + parser: { + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + // should pass + expect(parser.parseEval(`bar()::foo()::baz();`)).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/foreach.test.js b/test/snapshot/foreach.test.js new file mode 100644 index 000000000..939f3bfe5 --- /dev/null +++ b/test/snapshot/foreach.test.js @@ -0,0 +1,103 @@ +const parser = require("../main"); + +describe("foreach", function () { + it("as variable", function () { + expect( + parser.parseEval(` +foreach ($array as $var) { + echo $a; +} + `), + ).toMatchSnapshot(); + }); + + it("as variable by ref", function () { + expect( + parser.parseEval(` +foreach ($array as &$var) { + echo $a; +} + `), + ).toMatchSnapshot(); + }); + + it("as list", function () { + expect( + parser.parseEval(` +foreach ($array as list($a, $b)) { + echo $a; +} + `), + ).toMatchSnapshot(); + }); + + it("as short list", function () { + expect( + parser.parseEval(` +foreach ($array as [$a, $b]) { + echo $a; +} + `), + ).toMatchSnapshot(); + }); + + it("as list with key", function () { + expect( + parser.parseEval(` +foreach ($array as $v => list($a, $b)) { + echo $v; +} + `), + ).toMatchSnapshot(); + }); + + it("as short list with key", function () { + expect( + parser.parseEval(` +foreach ($array as $v => [$a, $b]) { + echo $v; +} + `), + ).toMatchSnapshot(); + }); + + it("unpacking", function () { + expect( + parser.parseEval(` +foreach ([...$var, 2, 3, 4] as $value) { + print_r($value); +} + `), + ).toMatchSnapshot(); + }); + + it("unpacking #2", function () { + expect( + parser.parseEval(` +foreach (array(...$var, 2, 3, 4) as $value) { + print_r($value); +} + `), + ).toMatchSnapshot(); + }); + + it("unpacking #3", function () { + expect( + parser.parseEval(` +foreach ([[...$var], 2, 3, 4] as $value) { + print_r($value); +} + `), + ).toMatchSnapshot(); + }); + + it("unpacking #4", function () { + expect( + parser.parseEval(` +foreach (array(array(...$var), 2, 3, 4) as $value) { + print_r($value); +} + `), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/function.test.js b/test/snapshot/function.test.js new file mode 100644 index 000000000..77d58e1df --- /dev/null +++ b/test/snapshot/function.test.js @@ -0,0 +1,277 @@ +const parser = require("../main"); + +describe("Function tests", function () { + it("test function parsing", function () { + const ast = parser.parseEval( + ` + function &foo($a = 1, callable $b, ?array &...$params) : ?boolean {} + $a = function &($b) use(&$c, $d) : array { + return true; + }; + $b = foo(...[1, null, 1, 2, 3]); + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test function union types", function () { + const ast = parser.parseEval( + ` + function foo(int|float $a = 1, Foo|Bar $b) : string|int {} + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test short function union types", function () { + const ast = parser.parseEval( + ` + fn (int|float $a = 1, Foo|Bar $b) : string|int => ""; + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test function intersection types", function () { + const ast = parser.parseEval( + ` + function foo(int&float $a = 1, Foo&Bar $b) : string&int {} + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test short function intersection types", function () { + const ast = parser.parseEval( + ` + fn (int&float $a = 1, Foo&Bar $b) : string&int => ""; + `, + ); + expect(ast).toMatchSnapshot(); + }); + + it("array pass by reference are not confused with intersection", function () { + expect( + parser.parseEval( + ` + function foo(array &$params) { + // inner comment + } + `, + ), + ).toMatchSnapshot(); + }); + + it("spread array pass by reference are not intersection", function () { + expect( + parser.parseEval( + ` + function &foo(array &$params) { + // inner comment + } + `, + ), + ).toMatchSnapshot(); + }); + + it("implement #113 : typehint nodes", function () { + expect( + parser.parseEval( + ` + function &foo(int $a = 1, float $b = 1, bool $c = 1, string $d, callable $e, int\\bar $f, ?array &...$params) : ?object { + // inner comment + } + `, + ), + ).toMatchSnapshot(); + }); + + it("implement #196 : set function name as identifier", function () { + const ast = parser.parseEval( + ` + function f /* f */($a) {} + `, + { + parser: { + extractDoc: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test variadic call error", function () { + expect(() => + parser.parseEval(`$b = foo(...[1, 2, 3], $a);`), + ).toThrowErrorMatchingSnapshot(); + }); + + it("test variadic function error 1", function () { + expect(() => + parser.parseEval(`function foo(...$bar, $baz) {}`), + ).toThrowErrorMatchingSnapshot(); + }); + + it("test variadic function error 2", function () { + expect(() => + parser.parseEval(`function foo(...$bar, ...$baz) {}`), + ).toThrowErrorMatchingSnapshot(); + }); + + it("test reserved word for function name error", function () { + const astErr = parser.parseEval(`function list() {}`, { + parser: { + version: "5.6", + suppressErrors: true, + }, + }); + expect(astErr).toMatchSnapshot(); + }); + + it("test static closure", function () { + const ast = parser.parseEval("$a = static function() {};"); + expect(ast).toMatchSnapshot(); + }); + + it("test arrow function php 7.4", function () { + const astErr = parser.parseEval(`function () {}`, { + parser: { + version: "7.4", + suppressErrors: true, + }, + }); + expect(astErr).toMatchSnapshot(); + }); + + it("test danging comma in function php 8.0", function () { + const astErr = parser.parseEval( + `function ( + $a, + $b, + $c, + ) {}`, + { + parser: { + version: "8.0", + }, + }, + ); + expect(astErr).toMatchSnapshot(); + }); + + it("test without danging comma in closure use-block php 8.0", function () { + const ast = parser.parseEval("$test = function () use ($one) {}", { + parser: { + version: "8.0", + }, + }); + expect(ast).toMatchSnapshot(); + }); + + it("test danging comma in closure use-block php 8.0", function () { + const ast = parser.parseEval("$test = function () use ($one,) {}", { + parser: { + version: "8.0", + }, + }); + expect(ast).toMatchSnapshot(); + }); + + it("test without danging comma in closure use-block with refs php 8.0", function () { + const ast = parser.parseEval("$test = function () use (&$one) {}", { + parser: { + version: "8.0", + }, + }); + expect(ast).toMatchSnapshot(); + }); + + it("test danging comma in closure use-block with refs php 8.0", function () { + const ast = parser.parseEval("$test = function () use (&$one) {}", { + parser: { + version: "8.0", + }, + }); + expect(ast).toMatchSnapshot(); + }); + + it("test danging comma in closure use-block with multiple php 8.0", function () { + const ast = parser.parseEval("$test = function () use ($one, $two,) {}", { + parser: { + version: "8.0", + }, + }); + expect(ast).toMatchSnapshot(); + }); + + it("test danging comma in closure use-block with multiple/refs php 8.0", function () { + const ast = parser.parseEval( + "$test = function ($one, $two) use ($three, &$four,) {}", + { + parser: { + version: "8.0", + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test double danging comma in closure use-block php 8.0", function () { + const astErr = parser.parseEval("$test = function () use ($one, ,) {}", { + parser: { + version: "8.0", + suppressErrors: true, + }, + }); + expect(astErr).toMatchSnapshot(); + }); + + it("Test readonly function properties are only for class constructor", function () { + const ast = parser.parseEval( + ` + function fun(public readonly int $id) {} + `, + { + parser: { + version: "8.1", + suppressErrors: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + test("first class callable support", function () { + expect( + parser.parseEval( + ` + $callable = strlen(...); + $callable = $item->doSomething(...); + $callable = $item::doSomething(...); + $callable = Foo::doSomething(...); + `, + { + parser: { + version: "8.1", + }, + }, + ), + ).toMatchSnapshot(); + }); + + test("first class callable support requires PHP 8.1+", function () { + expect( + parser.parseEval( + ` + $callable = strlen(...); + `, + { + parser: { + suppressErrors: true, + version: "8.0", + }, + }, + ), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/global.test.js b/test/snapshot/global.test.js new file mode 100644 index 000000000..8fa85b1ce --- /dev/null +++ b/test/snapshot/global.test.js @@ -0,0 +1,10 @@ +const parser = require("../main"); + +describe("global", function () { + it("simple", function () { + expect(parser.parseEval("global $var;")).toMatchSnapshot(); + }); + it("mutliple", function () { + expect(parser.parseEval("global $var, $foo;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/goto.test.js b/test/snapshot/goto.test.js new file mode 100644 index 000000000..5ca726523 --- /dev/null +++ b/test/snapshot/goto.test.js @@ -0,0 +1,8 @@ +const parser = require("../main"); + +describe("goto", function () { + it("simple", function () { + expect(parser.parseEval('goto a; echo "Foo";')).toMatchSnapshot(); + expect(parser.parseEval('goto longName; echo "Foo";')).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/graceful.test.js b/test/snapshot/graceful.test.js new file mode 100644 index 000000000..a55d2cca9 --- /dev/null +++ b/test/snapshot/graceful.test.js @@ -0,0 +1,106 @@ +const parser = require("../main"); + +describe("Test graceful mode", function () { + describe("to suppress errors", function () { + const test = parser.create({ + parser: { + suppressErrors: true, + }, + }); + + it("should contain 2 errors", function () { + expect( + test.parseEval( + [ + "$var = ", // 1. + "function() {", // 2. + "$foo = ", // 3. <-- missing expr + "}", // 4. + "}", // 5. <-- extra '}' token here + ].join("\n"), + ), + ).toMatchSnapshot(); + }); + + it("test expr", function () { + expect(test.parseEval("$a = $b -; $foo = $a;")).toMatchSnapshot(); + }); + + it("test class", function () { + expect(test.parseEval("class foo { foo const A = 1 ")).toMatchSnapshot(); + }); + + it("test flags", function () { + expect( + test.parseEval(` + final final interface foo { + abstract function func() + `), + ).toMatchSnapshot(); + }); + + it("test flags (2)", function () { + expect( + test.parseEval(` + final final class foo { + abstract function func() + `), + ).toMatchSnapshot(); + }); + + it("test flags (3)", function () { + expect( + test.parseEval(` + final final trait foo { + abstract function func() + `), + ).toMatchSnapshot(); + }); + + it("interface", function () { + expect( + test.parseEval("interface foo implement baz {}"), + ).toMatchSnapshot(); + }); + + it("trait", function () { + expect( + test.parseEval("trait foo extends bar implement baz {}"), + ).toMatchSnapshot(); + }); + + it("test function arguments", function () { + expect( + test.parseEval(` + $foo->bar($arg, ); + $foo = new bar($baz, ,$foo); + `), + ).toMatchSnapshot(); + }); + + it("test method chains", function () { + expect( + test.parseEval(` + $controller->expects($this->once()) + -> + `), + ).toMatchSnapshot(); + }); + + it("staticlookup", function () { + expect(test.parseEval("Order::{call()};")).toMatchSnapshot(); + }); + + it("should fail !", function () { + expect(test.parseEval("new Foo::{call()}();")).toMatchSnapshot(); + }); + + it("should fail with '{' and ']'", function () { + expect(test.parseEval("$obj{$foo];")).toMatchSnapshot(); + }); + + it("should fail with '[' and '}'", function () { + expect(test.parseEval("$obj[$bar};")).toMatchSnapshot(); + }); + }); +}); diff --git a/test/snapshot/heredoc.test.js b/test/snapshot/heredoc.test.js new file mode 100644 index 000000000..801949d37 --- /dev/null +++ b/test/snapshot/heredoc.test.js @@ -0,0 +1,508 @@ +const parser = require("../main"); + +describe("heredoc", function () { + it("simple", function () { + expect( + parser.parseEval(` +echo <<foo. +Now, I am printing some {$foo->bar[1]}. +This should print a capital 'A': \x41 +EOT; + `), + ).toMatchSnapshot(); + }); + + it("inside call", function () { + expect( + parser.parseEval(` +var_dump(array(<<bar[1]} + b + c + END; + `), + ).toMatchSnapshot(); + }); + + it("Flexible heredoc syntax: If the closing marker is indented further than any lines of the body", () => { + expect( + parser.parseEval( + ` + echo << { + expect( + parser.parseEval( + ` + echo << { + expect( + parser.parseEval( + ` + echo << { + expect( + parser.parseEval( + ` +echo << { + expect( + parser.parseEval( + ` +stringManipulator(<< { + expect( + parser.parseEval( + ` +$values = [<< { + expect( + parser.parseEval( + ` +$values = [<< { + expect( + parser.parseEval( + ` +$values = << { + expect( + parser.parseEval( + ` +$a = << { + expect( + parser.parseEval( + ` +$a = <<<'EOT' + a + + EOT; + +$b = <<<'EOT' + b + EOT; +`, + ), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/if.test.js b/test/snapshot/if.test.js new file mode 100644 index 000000000..478ebc3f5 --- /dev/null +++ b/test/snapshot/if.test.js @@ -0,0 +1,118 @@ +const parser = require("../main"); + +describe("Test IF statements", function () { + it("test common cases", function () { + const ast = parser.parseEval( + ` + if (true) { + echo "is true"; + } else if (false) { + echo "false"; + } elseif (false) { + echo "2nd"; + } else { + echo "else"; + } + `, + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test short form", function () { + const ast = parser.parseEval( + ` + if (true): + echo "is true"; + elseif (false): + echo "false"; + else: + echo "else"; + endif; + `, + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test various cases", function () { + const ast = parser.parseEval( + ` + if (true): + echo "is true"; + elseif (false): + echo "false"; + elseif (false): + echo "false"; + endif; + if (true): + echo "is true"; + else: + echo "false"; + endif; + `, + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("test issue #84", function () { + const ast = parser.parseCode( + ` + + + + `, + { + parser: { debug: false }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + it("test issue #168", () => { + // should be ok + let ast = parser.parseCode( + ` + `, + { + ast: { + withPositions: true, + withSource: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + + // should ignore ?> + ast = parser.parseCode( + ` + `, + { + ast: { + withPositions: true, + withSource: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + + // should include ';' + ast = parser.parseCode( + `", { + lexer: { + short_tags: true, + }, + }), + ).toMatchSnapshot(); + }); + + it("parse short echo", function () { + expect(parser.parseCode("")).toMatchSnapshot(); + }); + + it("#263 - expect inline", function () { + expect(parser.parseCode("")).toMatchSnapshot(); + }); + + it("parse asp tag", function () { + expect( + parser.parseCode("<% echo $b; %>", { + lexer: { + short_tags: true, + asp_tags: true, + }, + }), + ).toMatchSnapshot(); + }); + + it("parse asp echo tag", function () { + expect( + parser.parseCode("<%= $b %>", { + lexer: { + short_tags: true, + asp_tags: true, + }, + }), + ).toMatchSnapshot(); + }); + }); + + it("test comments", function () { + expect( + parser.parseCode( + ` + + <% + // another line %> + + list;")).toMatchSnapshot(); + }); + + it("test #1003 - null-safe operator with reserved keyword", function () { + expect(parser.parseCode("class;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/list.test.js b/test/snapshot/list.test.js new file mode 100644 index 000000000..44289c621 --- /dev/null +++ b/test/snapshot/list.test.js @@ -0,0 +1,100 @@ +const parser = require("../main"); + +describe("Test list expressions", function () { + it("test list statements", function () { + const ast = parser.parseEval(`list($a => list($c,$d,,$e,), $b) = [1, 2];`, { + ast: { + withPositions: true, + }, + }); + expect(ast).toMatchSnapshot(); + }); + + it("test short list", function () { + expect( + parser.parseEval( + `[$a => [$c,$d,,$e,], $b] = [1 => [5, 6, 7, 8, 9,], 2];`, + { + ast: { + withPositions: true, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("fix #150", function () { + const ast = parser.parseEval("list('foo' => $bar) = ['foo' => 'bar'];"); + expect(ast).toMatchSnapshot(); + }); + + it("fix #137", function () { + const ast = parser.parseEval("list(,,$a,,$b) = [null, 1, null, 2];", { + ast: { + withPositions: true, + }, + }); + expect(ast).toMatchSnapshot(); + }); + + it("handles nested shorthand lists (fix #512)", () => { + expect(parser.parseEval("[$a, [$b, $c]] = [1,[2,3]]")).toMatchSnapshot(); + }); + + it("handles comments in nested shorthand lists", () => { + expect( + parser.parseEval( + "[/*a*/$a/*b*/, /*c*/ [/*d*/$b/*e*/, /*f*/$c/*g*/]/*h*/]/*i*/ = [1,[2,3]] /*j*/", + { + parser: { extractDoc: true }, + }, + ), + ).toMatchSnapshot(); + }); + + it("list without trailing commas", () => { + expect(parser.parseEval("['foo', 'bar'] = $a")).toMatchSnapshot(); + }); + + it("array without trailing commas", () => { + expect(parser.parseEval("['foo', 'bar'] = $a")).toMatchSnapshot(); + }); + + it("array with trailing commas", () => { + expect(parser.parseEval("['foo', 'bar',] = $a")).toMatchSnapshot(); + }); + + it("array with trailing commas #2", () => { + expect(parser.parseEval("['foo', 'bar' ,] = $a")).toMatchSnapshot(); + }); + + it("array with trailing commas #3", () => { + expect(parser.parseEval("['foo', 'bar' , ] = $a")).toMatchSnapshot(); + }); + + it("array with multiple trailing commas", () => { + expect(parser.parseEval("['foo', 'bar',,] = $a")).toMatchSnapshot(); + }); + + it("array with multiple trailing commas #2", () => { + expect(parser.parseEval("['foo', 'bar',,,,,] = $a")).toMatchSnapshot(); + }); + + it("array with empty values", () => { + expect( + parser.parseEval("[,,,'foo',,, 'bar',,,'baz'] = $a"), + ).toMatchSnapshot(); + }); + + it("array with empty values #2", () => { + expect( + parser.parseEval("[,,,'foo',,, 'bar',,,'baz',] = $a"), + ).toMatchSnapshot(); + }); + + it("array with empty values #3", () => { + expect( + parser.parseEval("[,,,'foo',,, 'bar',,,'baz',,] = $a"), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/location.test.js b/test/snapshot/location.test.js new file mode 100644 index 000000000..8759f01cf --- /dev/null +++ b/test/snapshot/location.test.js @@ -0,0 +1,232 @@ +const parser = require("../main"); + +describe("Test locations", function () { + it.each([ + ["#230 : check location", "$var1 + $var2 + $var3;"], + [ + "#230 : check location on retif", + "$var1 + $var2 ? true : $false ? $innerTrue : $innerFalse;", + ], + ["#230 : check location on cast", "(string)$var1 + $var2;"], + ["#202 : include calling argument", "$foo->bar->baz($arg);"], + ["#164 : expr must include ;", "$a = $b + 1;"], + [ + "if/elseif/else", + 'if ($a > $b) echo "something"; elseif ($a < $b) echo "something"; else echo "something";', + ], + [ + "if/elseif/else block", + 'if ($a > $b) { echo "something"; } elseif ($a < $b) { echo "something"; } else { echo "something"; }', + ], + ["switch", "switch ($i) {}"], + ["switch case", 'switch ($i) { case 0: echo "something"; break; }'], + ["switch default", 'switch ($i) { default: echo "something"; }'], + ["for", 'for ($i = 1; $i <= 10; $i++) echo "something";'], + ["for block", 'for ($i = 1; $i <= 10; $i++) { echo "something"; }'], + ["foreach", 'foreach ($arr as $value) echo "something";'], + ["foreach block", 'foreach ($arr as $value) { echo "something"; }'], + ["while", 'while(true) echo "something";'], + ["while block", 'while(true) { echo "something"; }'], + ["do", "do { echo $i; } while(true);"], + ["return", "return 1;"], + ["break", "break;"], + + ["continue", "continue;"], + ["global", "global $a;"], + ["static", "static $a = 1;"], + ["static multiple", "static $a = 1, $b = 2, $c = 3;"], + ["echo", 'echo "something";'], + ["unset", "unset($foo);"], + ["declare", "declare(ticks=1);"], + ["declare block", 'declare(ticks=1) { echo "something"; }'], + ["try", "try new Exception();"], + ["goto", "goto a;"], + ["goto #2", "goto longName;"], + ["label", 'a: echo "something";'], + ["label #2", 'longName: echo "something";'], + ["function", 'function foo() { echo "something"; }'], + ["class", "class Foo {}"], + ["abstract class", "abstract class Foo {}"], + ["final class", "final class Foo {}"], + ["class (inner statement)", "function foo() { class Foo {} }"], + [ + "abstract class (inner statement)", + "function foo() { abstract class Foo {} }", + ], + ["final class (inner statement)", "function foo() { final class Foo {} }"], + ["interface", "interface Foo {}"], + ["trait", "trait Foo {}"], + ["namespace", "namespace my\\name;"], + ["namespace backets", 'namespace my\\name { echo "something"; }'], + ["string double quotes", '"string";'], + ["string single quotes", "'string';"], + ["number", "2112;"], + ["negative number", "-2112;"], + ["magic", "__DIR__;"], + ["ternary", '$valid ? "yes" : "no";'], + ["ternary no true expression", '$valid ?: "no";'], + ["variable", "$var;"], + ["assign", "$var = true;"], + ["assign by ref", "$var = &$var;"], + ["assign mutliple", "$var = $other = true;"], + ["unary", "!$var;"], + ["pre", "++$var;"], + ["post", "$var++;"], + ["yield", "yield $var;"], + ["yield from", "yield from from();"], + ["bin", "$var = $var + 100;"], + ["array", "array(1, 2, 3);"], + ["array nested", "array(array(1, 2, 3));"], + ["array short form", "[1, 2, 3];"], + ["array short form nested", "[[1, 2, 3]];"], + [ + "array with keys, byRef and unpack", + `$var = [1, 'foo', 'test' => $foo, 'test' => &$foo, ...$var];`, + ], + ["clone", "clone $var;"], + ["new", "new Foo();"], + ["new anonymous class", "$var = new class {};"], + ["eval", 'eval("code");'], + ["exit", "exit(1);"], + ["print", 'print "something";'], + ["include", 'include "something";'], + ["isset", "$var = isset($var);"], + ["empty", "$var = empty($var);"], + ["silent", "$var = @call();"], + ["variadic", "call(...$var);"], + ["try/catch/finally", "try {} catch (Exception $e) {} finally {}"], + [ + "nowdoc", + `<<<'EOD' +Text +EOD;`, + ], + [ + "nowdoc assign", + `$var = <<<'EOD' +Text +EOD;`, + ], + [ + "encapsed heredoc", + `<<each() // Comment + // Comment + ->map() // Comment + // Comment + ->first() // Comment + // Comment + ->dump(); + `, + ], + [ + "staticlookup", + ` + $var = $var + // Comment + ::each() // Comment + // Comment + ::map() // Comment + // Comment + ::first() // Comment + // Comment + ::dump(); + `, + ], + [ + "offsetlookup", + ` + $var = $var + // Comment + [ 'foo' ] // Comment + // Comment + ['bar'] // Comment + // Comment + ['baz'] // Comment + // Comment + ['qqq']; + `, + ], + ["assign []", `$var[] = $var`], + ["single call", `call();`], + ])("test %s", (_, code) => { + expect( + parser.parseEval(code, { + ast: { + withPositions: true, + withSource: true, + }, + }), + ).toMatchSnapshot(); + }); + + it("#164 : expr should avoid ?>", function () { + expect( + parser.parseCode("", { + ast: { + withPositions: true, + withSource: true, + }, + }), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/loop.test.js b/test/snapshot/loop.test.js new file mode 100644 index 000000000..dd9601ecc --- /dev/null +++ b/test/snapshot/loop.test.js @@ -0,0 +1,105 @@ +const parser = require("../main"); + +describe("Test loops statements (for, while)", function () { + describe("test while", function () { + it("test default form", function () { + expect( + parser.parseEval(` + while(true) { + echo "go"; + } + `), + ).toMatchSnapshot(); + }); + + it("test short form", function () { + expect( + parser.parseEval(` + while(true): + echo "short"; + endwhile; + `), + ).toMatchSnapshot(); + }); + }); + + it("test do", function () { + expect( + parser.parseEval( + ` + do { + echo "something"; + } while(true); + `, + { + parser: { debug: false }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test for", function () { + expect( + parser.parseEval( + ` + for($i = 0, $b = 0; $i < 10, $ok; $i++) + echo $i; + for(;;): + echo $ok; + continue 5; + continue(5); + endfor; + `, + { + parser: { debug: false }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test foreach", function () { + expect( + parser.parseEval( + ` + foreach(&$foo as $v) + echo "$k -> $v\n"; + foreach( + [[1,2], [3,4]] as + $a => + [$c, $d] + ): + echo "$a -> $b\n"; + endforeach; + `, + { + parser: { debug: false }, + }, + ), + ).toMatchSnapshot(); + }); + it("fix #122", function () { + // https://github.com/glayzzle/php-parser/issues/122 + expect( + parser.parseEval( + ` + foreach($foo as $bar => array($foo)) + echo "$k -> $v\n"; + `, + { + parser: { suppressErrors: true }, + }, + ), + ).toMatchSnapshot(); + expect( + parser.parseEval( + ` + foreach($foo as [$bar] => $foo) + echo "$k -> $v\n"; + `, + { + parser: { suppressErrors: true }, + }, + ), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/magic.test.js b/test/snapshot/magic.test.js new file mode 100644 index 000000000..d92eec895 --- /dev/null +++ b/test/snapshot/magic.test.js @@ -0,0 +1,31 @@ +const parser = require("../main"); + +describe("magic", function () { + it("__LINE__", function () { + expect(parser.parseEval("__LINE__;")).toMatchSnapshot(); + }); + it("__LINE__ lowercase", function () { + expect(parser.parseEval("__line__;")).toMatchSnapshot(); + }); + it("__FILE__", function () { + expect(parser.parseEval("__FILE__;")).toMatchSnapshot(); + }); + it("__DIR__", function () { + expect(parser.parseEval("__DIR__;")).toMatchSnapshot(); + }); + it("__FUNCTION__", function () { + expect(parser.parseEval("__FUNCTION__;")).toMatchSnapshot(); + }); + it("__CLASS__", function () { + expect(parser.parseEval("__CLASS__;")).toMatchSnapshot(); + }); + it("__TRAIT__", function () { + expect(parser.parseEval("__TRAIT__;")).toMatchSnapshot(); + }); + it("__METHOD__", function () { + expect(parser.parseEval("__METHOD__;")).toMatchSnapshot(); + }); + it("__NAMESPACE__", function () { + expect(parser.parseEval("__NAMESPACE__;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/match.test.js b/test/snapshot/match.test.js new file mode 100644 index 000000000..4ccd0bbbc --- /dev/null +++ b/test/snapshot/match.test.js @@ -0,0 +1,62 @@ +const parser = require("../main"); + +describe("match", () => { + it("can be parsed", () => { + const ast = parser.parseEval(` + $test = match($a) { + true => 'yes', + false => 'no', + default => null + }; + `); + expect(ast).toMatchSnapshot(); + }); + + it("can have lhs, functions", () => { + const ast = parser.parseEval(` + $test = match(true) { + test($a), abc($b) => 'yes', + default => null + }; + `); + expect(ast).toMatchSnapshot(); + }); + + it("can have multiple values", () => { + const ast = parser.parseEval(` + $test = match(trye) { + 0,1,2,3 => run(), + default => null + }; + `); + expect(ast).toMatchSnapshot(); + }); + it("can have hanging comma", () => { + const ast = parser.parseEval(` + $test = match($test) { + true, => 'ok', + false => throw new Exception('Nope'), + }; + `); + expect(ast).toMatchSnapshot(); + }); + it("does not support older php than 8", () => { + expect(() => { + new parser({ parser: { version: 704 } }).parseEval(` + $test = match($test) { + true => 'ok', + false => 'Nope!', + }; + `); + }).toThrow(SyntaxError); + }); + it("can be nested", () => { + const ast = parser.parseEval(` + $v = match(callMe(1,2,3)) { + null => match($err) { 1 => 'Connect', 2 => 'Auth'}, + match($a) {true => 0, false => -1} => 'Ok' + }; + `); + expect(ast).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/namespace.test.js b/test/snapshot/namespace.test.js new file mode 100644 index 000000000..b39f1602d --- /dev/null +++ b/test/snapshot/namespace.test.js @@ -0,0 +1,215 @@ +const parser = require("../main"); + +describe("Test namespace statements", function () { + it("fix #246 - doesn't work properly for `FULL_QUALIFIED_NAME`", function () { + expect( + parser.parseEval(` + $obj = new \\Foo(); + `), + ).toMatchSnapshot(); + }); + it("allow trailing comma for grouped namespaces #177", function () { + expect( + parser.parseEval(` + use Foo\\Bar\\ { + Foo, + Bar, + Baz, + };`), + ).toMatchSnapshot(); + }); + it("test single namespace", function () { + expect( + parser.parseEval( + ` + namespace foo; + use bar\\baz as barBaz; + use const bar\\baz as barBaz, baz\\boo as bazBoo; + use function bar\\baz as barBaz, baz\\boo as bazBoo; + use bar\\baz { + const FOO as BAZ_FOO, + function BOO as BAZ_BOO + }; + use const azerty { + A as AZERTY_A, + B as AZERTY_B + }; + $a = namespace\\barBaz; + $b = \\barBaz; + $c = barBaz\\foo; + $d = barBaz; + `, + { + parser: { + debug: false, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test multiple namespace", function () { + expect( + parser.parseEval( + ` + namespace \\foo { + $i++; + } + namespace { + $b++; + } + `, + { + parser: { + debug: false, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test namespace keyword", function () { + expect( + parser.parseEval( + ` + namespace\\foo(); + $var = namespace\\bar; + `, + { + parser: { + debug: false, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test keywords", function () { + expect( + parser.parseEval( + ` + namespace\\enum(); + \\foo\\trait\\class(); + use \\foo\\bar\\{ a, b }; + $var = namespace\\bar; + `, + { + parser: { + debug: false, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test bare namespace separator", function () { + expect( + parser.parseEval(`\\`, { + parser: { + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + }); + + it("test namespace error", function () { + expect( + parser.parseEval( + ` + namespace $var = true; + `, + { + parser: { + debug: false, + suppressErrors: true, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("check namespace", function () { + // @todo + }); + + it("check use", function () { + // @todo + }); + + it("check resolution", function () { + // @todo + }); + + it("check silent mode", function () { + expect( + parser.parseEval( + ` + namespace $var = true; + `, + { + parser: { + debug: false, + suppressErrors: true, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("work with declare statement", function () { + expect( + parser.parseEval(` + declare(strict_types=1); + namespace foo; + class bar {} + `), + ).toMatchSnapshot(); + }); + + describe("read usegroup location correctly", function () { + const testString = ` + namespace Test\\test\\test; + + use Some\\other\\test; + + /** + * @property \\Test\\test $test + */ + class Foo extends Bar implements Baz, Buzz { + public $test; + + function test() { + return true; + } + + public function &passByReferenceTest() { + $a = 1; + return $a; + } + } + `; + + it("without docs", function () { + expect( + parser.parseEval(testString, { + ast: { + withPositions: true, + }, + }), + ).toMatchSnapshot(); + }); + + it("with docs", function () { + expect( + parser.parseEval(testString, { + ast: { + withPositions: true, + }, + parser: { + extractDoc: true, + }, + }), + ).toMatchSnapshot(); + }); + }); +}); diff --git a/test/snapshot/new.test.js b/test/snapshot/new.test.js new file mode 100644 index 000000000..db340d959 --- /dev/null +++ b/test/snapshot/new.test.js @@ -0,0 +1,88 @@ +const parser = require("../main"); + +describe("new", function () { + it("#348 - byref usage deprecated", function () { + expect( + parser.parseEval("$a =& new Foo();", { + parser: { + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + }); + it("simple", function () { + expect(parser.parseEval("new Foo();")).toMatchSnapshot(); + }); + it("variable", function () { + expect(parser.parseEval("new $var;")).toMatchSnapshot(); + }); + it("simple (2)", function () { + expect(parser.parseEval("new \\Foo();")).toMatchSnapshot(); + }); + it("simple (3)", function () { + expect(parser.parseEval("new Foo\\Foo();")).toMatchSnapshot(); + }); + it("simple (4)", function () { + expect(parser.parseEval("new \\Foo\\Foo();")).toMatchSnapshot(); + }); + it("no parens", function () { + expect(parser.parseEval("new Foo;")).toMatchSnapshot(); + }); + it("anonymous", function () { + expect(parser.parseEval("new class() {};")).toMatchSnapshot(); + }); + it("anonymous no parens", function () { + expect(parser.parseEval("new class {};")).toMatchSnapshot(); + }); + it("anonymous with argument", function () { + expect(parser.parseEval("new class($var) {};")).toMatchSnapshot(); + }); + it("anonymous with multiple argument", function () { + expect( + parser.parseEval("new class($one, $two, $three) {};"), + ).toMatchSnapshot(); + }); + it("static array", () => { + expect( + parser.parseEval("return new self::$mapping[$map]();"), + ).toMatchSnapshot(); + }); + it("parent", function () { + expect(parser.parseEval("new parent();")).toMatchSnapshot(); + }); + it("self", function () { + expect(parser.parseEval("new self();")).toMatchSnapshot(); + }); + it("static", function () { + expect(parser.parseEval("new static();")).toMatchSnapshot(); + }); + it("with arguments", function () { + expect( + parser.parseEval('new Foo("constructor", "bar");'), + ).toMatchSnapshot(); + }); + it("trailing comma", function () { + expect( + parser.parseEval('new Foo("constructor", "bar",);'), + ).toMatchSnapshot(); + }); + it("anonymous class", function () { + expect(parser.parseEval("$var = new class {};")).toMatchSnapshot(); + }); + it("anonymous class #2", function () { + expect(parser.parseEval("$var = new class($var) {};")).toMatchSnapshot(); + }); + it("anonymous class #3", function () { + expect( + parser.parseEval( + "$var = new class($var) extends SomeClass implements SomeInterface {};", + ), + ).toMatchSnapshot(); + }); + it("result from function", function () { + expect(parser.parseEval("$a = new (b('c')('d'));")).toMatchSnapshot(); + }); + it("result from function with arguments", function () { + expect(parser.parseEval("$a = new (b('c')('d'))('e');")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/nowdoc.test.js b/test/snapshot/nowdoc.test.js new file mode 100644 index 000000000..4690d23fc --- /dev/null +++ b/test/snapshot/nowdoc.test.js @@ -0,0 +1,159 @@ +const parser = require("../main"); + +describe("nowdoc", function () { + it("simple", function () { + expect( + parser.parseEval(` +echo <<<'EOD' +Example of string +spanning multiple lines +using heredoc syntax. +EOD; + `), + ).toMatchSnapshot(); + }); + + it("with space between <<< and label", function () { + expect( + parser.parseEval(` +echo <<< 'EOD' +Example of string +spanning multiple lines +using heredoc syntax. +EOD; + `), + ).toMatchSnapshot(); + }); + + it("with variables", function () { + expect( + parser.parseEval(` +echo <<<'EOT' +My name is "$name". I am printing some $foo->foo. +Now, I am printing some {$foo->bar[1]}. +This should print a capital 'A': \x41 +EOT; + `), + ).toMatchSnapshot(); + }); + + it("inside call", function () { + expect( + parser.parseEval(` +var_dump(array(<<<'EOD' +foobar! +EOD +)); + `), + ).toMatchSnapshot(); + }); + + it("inside function", function () { + expect( + parser.parseEval(` +function foo() +{ + static $bar = <<<'LABEL' +Nothing in here... +LABEL; +} + `), + ).toMatchSnapshot(); + }); + + it("inside class", function () { + expect( + parser.parseEval(` +class foo { + const BAR = <<<'FOOBAR' +Constant example +FOOBAR; + + public $baz = <<<'FOOBAR' +Property example +FOOBAR; +} + `), + ).toMatchSnapshot(); + }); + + it("empty", function () { + expect( + parser.parseEval(` +echo <<<'TEST' +TEST; + `), + ).toMatchSnapshot(); + }); + + it("only newline", function () { + expect( + parser.parseEval(` +echo <<<'TEST' + +TEST; + `), + ).toMatchSnapshot(); + }); + + it("space between <<< and label", function () { + expect( + parser.parseEval(` +echo <<< 'TEST' + a + b +c +TEST; + `), + ).toMatchSnapshot(); + }); + + it("tab between <<< and label", function () { + expect( + parser.parseEval(` +echo <<<\t'TEST' + a + b +c +TEST; + `), + ).toMatchSnapshot(); + }); + + it("Flexible nowdoc syntax: 4 spaces of indentation", function () { + expect( + parser.parseEval(` + echo <<<'END' + a + b + c + END; + `), + ).toMatchSnapshot(); + }); + + it("Flexible nowdoc syntax: with variables", function () { + expect( + parser.parseEval(` + echo <<<'END' + a + {$foo->bar[1]} + b + c + END; + `), + ).toMatchSnapshot(); + }); + + it("Followed by string interpolation", function () { + expect( + parser.parseEval(` + $x = <<<'NOWDOC' + ... + NOWDOC; + + $y = "_$z"; + `), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/nullsavepropertylookup.test.js b/test/snapshot/nullsavepropertylookup.test.js new file mode 100644 index 000000000..50e82ac32 --- /dev/null +++ b/test/snapshot/nullsavepropertylookup.test.js @@ -0,0 +1,18 @@ +const parser = require("../main"); + +describe("nullsavepropertylookup", function () { + it("simple", function () { + expect(parser.parseEval("$obj?->property;")).toMatchSnapshot(); + }); + it("variable", function () { + expect(parser.parseEval("$obj?->$property;")).toMatchSnapshot(); + }); + it("call", function () { + expect(parser.parseEval("$obj?->call();")).toMatchSnapshot(); + }); + it("multiple", function () { + expect( + parser.parseEval("$obj?->property_1?->property_2;"), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/number.test.js b/test/snapshot/number.test.js new file mode 100644 index 000000000..84b6960b0 --- /dev/null +++ b/test/snapshot/number.test.js @@ -0,0 +1,47 @@ +const parser = require("../main"); + +describe("Test numbers", function () { + it("test common cases", function () { + expect( + parser.parseEval(` + 1234; + $a = -1.5; + $b = 1234; + $c = 9223372036854775807; + $c = 9223372036854775808; + $d = 0x1A; + $d = 0xFF; + $e = 0b1011; + $f = 0123; + $g = 1.2e3; + $h = 7E-10; + `), + ).toMatchSnapshot(); + }); + + it.each([ + ["hexa without hex", "$a = 0xx;"], + ["binary with 2", "$b = 0b2;"], + ["multiple points", "$b = 1.0.5;"], + // @fixme : PHP Parse error: Invalid numeric literal in %s + // ["octal with 9", "$c = 01239;"], + ["exponent with letter", "$d = 7E-a;"], + ["variant (for coverage)", "$d = 7e+a;"], + ["exponent empty", "$e = 7EX;"], + ["underscore #1", "$e = 7__0;"], + ["underscore #2", "$e = 7._0;"], + ["underscore #3", "$e = 7_.0;"], + ["underscore #4", "$e = 7e_0;"], + ["underscore #5", "$e = 7_e0;"], + ])("%s", function (_, code) { + const ast = parser.parseEval(code, { + parser: { + suppressErrors: true, + }, + }); + // expect to fail + expect(ast.errors.length).toBeGreaterThan(0); + // check structure + expect(ast).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/offsetlookup.test.js b/test/snapshot/offsetlookup.test.js new file mode 100644 index 000000000..6e65f832c --- /dev/null +++ b/test/snapshot/offsetlookup.test.js @@ -0,0 +1,50 @@ +const parser = require("../main"); + +describe("offsetlookup", function () { + it("simple", function () { + expect(parser.parseEval('$obj["index"];')).toMatchSnapshot(); + }); + it("variable", function () { + expect(parser.parseEval("$obj[$var];")).toMatchSnapshot(); + }); + it("call", function () { + expect(parser.parseEval("$obj[$var]();")).toMatchSnapshot(); + }); + it("multiple", function () { + expect(parser.parseEval('$obj["first"]["second"];')).toMatchSnapshot(); + }); + it("simple (curly)", function () { + expect(parser.parseEval('$obj{"index"};')).toMatchSnapshot(); + }); + it("variable (curly)", function () { + expect(parser.parseEval("$obj{$var};")).toMatchSnapshot(); + }); + it("call (curly)", function () { + expect(parser.parseEval("$obj{$var}();")).toMatchSnapshot(); + }); + it("multiple (curly)", function () { + expect(parser.parseEval('$obj{"first"}{"second"};')).toMatchSnapshot(); + }); + it("inside propertylookup", function () { + expect( + parser.parseEval(` +$foo->bzr_[1]; +$foo->bzr_['string']; +$foo->bzr_[$baz]; +$foo->bzr_[$baz->foo]; +$foo->bzr_[$var ? 'one' : 'two']; + `), + ).toMatchSnapshot(); + }); + it("inside propertylookup (curly)", function () { + expect( + parser.parseEval(` +$foo->bzr_{1}; +$foo->bzr_{'string'}; +$foo->bzr_{$baz}; +$foo->bzr_{$baz->foo}; +$foo->bzr_{$var ? 'one' : 'two'}; + `), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/parentreference.test.js b/test/snapshot/parentreference.test.js new file mode 100644 index 000000000..98e6bc5c7 --- /dev/null +++ b/test/snapshot/parentreference.test.js @@ -0,0 +1,28 @@ +const parser = require("../main"); + +describe("parentreference", function () { + it("variable", function () { + expect(parser.parseEval("parent::$var;")).toMatchSnapshot(); + }); + it("constant", function () { + expect(parser.parseEval("parent::CONSTANT;")).toMatchSnapshot(); + }); + it("call", function () { + expect(parser.parseEval("parent::call();")).toMatchSnapshot(); + }); + it("uppercase", function () { + expect(parser.parseEval("PARENT::call();")).toMatchSnapshot(); + }); + it("argument", function () { + expect(parser.parseEval("function foo(parent $arg) {}")).toMatchSnapshot(); + }); + it("argument (uppercase)", function () { + expect(parser.parseEval("function foo(PARENT $arg) {}")).toMatchSnapshot(); + }); + it("return type declarations", function () { + expect(parser.parseEval("function foo($arg): parent {}")).toMatchSnapshot(); + }); + it("return type declarations (uppercase)", function () { + expect(parser.parseEval("function foo($arg): PARENT {}")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/php5.test.js b/test/snapshot/php5.test.js new file mode 100644 index 000000000..f1dc07ba0 --- /dev/null +++ b/test/snapshot/php5.test.js @@ -0,0 +1,13 @@ +const parser = require("../main"); + +describe("Test syntax parsing without PHP7 support", function () { + it("special keywords should fail", function () { + const ast = parser.parseEval("class foo { function list() { } }", { + parser: { + version: "5.6", + suppressErrors: true, + }, + }); + expect(ast).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/php73.test.js b/test/snapshot/php73.test.js new file mode 100644 index 000000000..8bc4d9d54 --- /dev/null +++ b/test/snapshot/php73.test.js @@ -0,0 +1,76 @@ +const parser = require("../main"); + +describe("Test syntax parsing with PHP 73 support", function () { + it("https://wiki.php.net/rfc/list_reference_assignment", function () { + const ast = parser.parseEval( + "[$a, &$b] = $array; list($a, &$b) = $array;", + { + parser: { + version: "7.3", + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("https://wiki.php.net/rfc/trailing-comma-function-calls", function () { + const ast = parser.parseEval( + ` + $newArray = array_merge( + $arrayOne, + $arrayTwo, + ['foo', 'bar'], + ); + + $foo = new Foo( + 'constructor', + 'bar', + ); + + $foo->bar( + 'method', + 'bar', + ); + + $foo( + 'invoke', + 'bar', + ); + + unset($foo, $bar,); + var_dump(isset($foo, $bar,)); + `, + { + parser: { + version: "7.3", + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); + + it("https://wiki.php.net/rfc/trailing-comma-function-calls#errors", function () { + const ast = parser.parseEval( + ` + # Parse error + function bar($a, $b,) { + // + } + # Parse error + foo(,); + + # Parse error + foo('function', 'bar',,); + # Also parse error + foo(, 'function', 'bar'); + `, + { + parser: { + version: "7.3", + suppressErrors: true, + }, + }, + ); + expect(ast).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/post.test.js b/test/snapshot/post.test.js new file mode 100644 index 000000000..016565309 --- /dev/null +++ b/test/snapshot/post.test.js @@ -0,0 +1,34 @@ +const parser = require("../main"); + +describe("post", function () { + it("++", function () { + expect(parser.parseEval("$var++;")).toMatchSnapshot(); + }); + it("--", function () { + expect(parser.parseEval("$var--;")).toMatchSnapshot(); + }); + it("++ and parens", function () { + expect(parser.parseEval("($var++);")).toMatchSnapshot(); + }); + it("-- and parens", function () { + expect(parser.parseEval("($var--);")).toMatchSnapshot(); + }); + it("++ and + unary", function () { + expect(parser.parseEval("+($var++);")).toMatchSnapshot(); + }); + it("++ and - unary", function () { + expect(parser.parseEval("-$var++;")).toMatchSnapshot(); + }); + it("++ and - unary (with parens)", function () { + expect(parser.parseEval("-($var++);")).toMatchSnapshot(); + }); + it("-- and + unary", function () { + expect(parser.parseEval("+$var--;")).toMatchSnapshot(); + }); + it("-- and + unary (with parens)", function () { + expect(parser.parseEval("+($var--);")).toMatchSnapshot(); + }); + it("-- and unary -", function () { + expect(parser.parseEval("-($var--);")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/pre.test.js b/test/snapshot/pre.test.js new file mode 100644 index 000000000..5276ef10f --- /dev/null +++ b/test/snapshot/pre.test.js @@ -0,0 +1,34 @@ +const parser = require("../main"); + +describe("pre", function () { + it("++", function () { + expect(parser.parseEval("++$var;")).toMatchSnapshot(); + }); + it("--", function () { + expect(parser.parseEval("--$var;")).toMatchSnapshot(); + }); + it("++ and parens", function () { + expect(parser.parseEval("(++$var);")).toMatchSnapshot(); + }); + it("-- and parens", function () { + expect(parser.parseEval("(--$var);")).toMatchSnapshot(); + }); + it("++ and + unary", function () { + expect(parser.parseEval("+(++$var);")).toMatchSnapshot(); + }); + it("++ and - unary", function () { + expect(parser.parseEval("-++$var;")).toMatchSnapshot(); + }); + it("++ and - unary (with parens)", function () { + expect(parser.parseEval("-(++$var);")).toMatchSnapshot(); + }); + it("-- and + unary", function () { + expect(parser.parseEval("+--$var;")).toMatchSnapshot(); + }); + it("-- and + unary (with parens)", function () { + expect(parser.parseEval("+(--$var);")).toMatchSnapshot(); + }); + it("-- and unary -", function () { + expect(parser.parseEval("-(--$var);")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/print.test.js b/test/snapshot/print.test.js new file mode 100644 index 000000000..9e3858aa3 --- /dev/null +++ b/test/snapshot/print.test.js @@ -0,0 +1,7 @@ +const parser = require("../main"); + +describe("print", function () { + it("simple", function () { + expect(parser.parseEval('print "string";')).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/property.test.js b/test/snapshot/property.test.js new file mode 100644 index 000000000..0761a087a --- /dev/null +++ b/test/snapshot/property.test.js @@ -0,0 +1,124 @@ +const parser = require("../main"); + +describe("property", () => { + it("var", () => { + expect(parser.parseEval("class Foo { var $property; }")).toMatchSnapshot(); + }); + it("var with value", () => { + expect( + parser.parseEval("class Foo { var $property = 10; }"), + ).toMatchSnapshot(); + }); + it("public", () => { + expect( + parser.parseEval("class Foo { public $property; }"), + ).toMatchSnapshot(); + }); + it("public with value", () => { + expect( + parser.parseEval("class Foo { public $property = 10; }"), + ).toMatchSnapshot(); + }); + it("protected", () => { + expect( + parser.parseEval("class Foo { protected $property; }"), + ).toMatchSnapshot(); + }); + it("protected with value", () => { + expect( + parser.parseEval("class Foo { protected $property = 10; }"), + ).toMatchSnapshot(); + }); + it("private", () => { + expect( + parser.parseEval("class Foo { private $property; }"), + ).toMatchSnapshot(); + }); + it("private with value", () => { + expect( + parser.parseEval("class Foo { private $property = 10; }"), + ).toMatchSnapshot(); + }); + it("public static", () => { + expect( + parser.parseEval("class Foo { public static $property; }"), + ).toMatchSnapshot(); + }); + it("public static with value", () => { + expect( + parser.parseEval("class Foo { public static $property = 10; }"), + ).toMatchSnapshot(); + }); + it("without value", () => { + expect( + parser.parseEval("class Foo { public $property; }"), + ).toMatchSnapshot(); + }); + it("with string number value", () => { + expect( + parser.parseEval("class Foo { public $property = 10; }"), + ).toMatchSnapshot(); + }); + it("with single quotes string value", () => { + expect( + parser.parseEval("class Foo { public $property = 'string'; }"), + ).toMatchSnapshot(); + }); + it("with double quotes string value", () => { + expect( + parser.parseEval('class Foo { public $property = "string"; }'), + ).toMatchSnapshot(); + }); + it("with boolean value", () => { + expect( + parser.parseEval("class Foo { public $property = true; }"), + ).toMatchSnapshot(); + }); + it("with bin value", () => { + expect( + parser.parseEval("class Foo { public $property = 'hello ' . 'world'; }"), + ).toMatchSnapshot(); + }); + it("with bin value 2", () => { + expect( + parser.parseEval("class Foo { public $property = 1 + 2; }"), + ).toMatchSnapshot(); + }); + it("with heredoc value", () => { + expect( + parser.parseEval(` +class Foo { + public $property = << { + expect( + parser.parseEval(` +class Foo { + public $property = <<<'EOD' +hello world +EOD; +} + `), + ).toMatchSnapshot(); + }); + it("with constant value", () => { + expect( + parser.parseEval("class Foo { public $property = CONSTANT; }"), + ).toMatchSnapshot(); + }); + it("with array value", () => { + expect( + parser.parseEval("class Foo { public $property = array(true, false); }"), + ).toMatchSnapshot(); + }); + it("with short array value", () => { + expect( + parser.parseEval("class Foo { public $property = [true, false]; }"), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/propertylookup.test.js b/test/snapshot/propertylookup.test.js new file mode 100644 index 000000000..2b3f7347b --- /dev/null +++ b/test/snapshot/propertylookup.test.js @@ -0,0 +1,19 @@ +const parser = require("../main"); + +describe("propertylookup", function () { + it("fix 128 - Don't have curly for propertylookup", function () { + expect(parser.parseEval("$this->{foo};$this->bar;")).toMatchSnapshot(); + }); + it("simple", function () { + expect(parser.parseEval("$obj->property;")).toMatchSnapshot(); + }); + it("variable", function () { + expect(parser.parseEval("$obj->$property;")).toMatchSnapshot(); + }); + it("call", function () { + expect(parser.parseEval("$obj->call();")).toMatchSnapshot(); + }); + it("multiple", function () { + expect(parser.parseEval("$obj->property_1->property_2;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/propertystatement.test.js b/test/snapshot/propertystatement.test.js new file mode 100644 index 000000000..6c9707a51 --- /dev/null +++ b/test/snapshot/propertystatement.test.js @@ -0,0 +1,20 @@ +const parser = require("../main"); + +describe("propertystatement", () => { + it("simple", () => { + expect(parser.parseEval("class Foo { public $dsn; }")).toMatchSnapshot(); + }); + it("simple (var)", () => { + expect(parser.parseEval("class Foo { var $dsn; }")).toMatchSnapshot(); + }); + it("multiple", () => { + expect( + parser.parseEval("class Foo { public $dsn, $username, $password; }"), + ).toMatchSnapshot(); + }); + it("multiple (var)", () => { + expect( + parser.parseEval("class Foo { var $dsn, $username, $password; }"), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/return.test.js b/test/snapshot/return.test.js new file mode 100644 index 000000000..031888e2f --- /dev/null +++ b/test/snapshot/return.test.js @@ -0,0 +1,17 @@ +const parser = require("../main"); + +describe("return", function () { + it("simple", function () { + expect(parser.parseEval('return "string";')).toMatchSnapshot(); + }); + it("no expression", function () { + expect(parser.parseEval("return;")).toMatchSnapshot(); + }); + it("should fail when no ';' at end", function () { + expect( + parser.parseEval("return", { + parser: { suppressErrors: true }, + }), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/scalar.test.js b/test/snapshot/scalar.test.js new file mode 100644 index 000000000..edda34a3e --- /dev/null +++ b/test/snapshot/scalar.test.js @@ -0,0 +1,25 @@ +const parser = require("../main"); + +describe("Test scalar statements", function () { + it.each([ + ["test constants", "$a = foo::ref[-5];"], + ["test constants #2", "$a = Foo;"], + ["test constants #3", "$a = $var::foo;"], + [ + "test dereferencable", + ` + $a = foo::bar()[5]->test; + $b = (new test())->foo(); + $c = (foo())[5]; + $d = (function($a) { return $a * 2; })(5); + `, + ], + ["test dereferencable_scalar", "$var = array(1);"], + ["test dereferencable_scalar #2", "$var = [1];"], + ["test dereferencable_scalar #3", '$var = "test";'], + ["php 8.1 explicit octal", "$var = 0o123 + 0o001_234;"], + ["implicit octal", "$var = 0123;"], + ])("%s", function (_, code) { + expect(parser.parseEval(code)).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/selfreference.test.js b/test/snapshot/selfreference.test.js new file mode 100644 index 000000000..cf501c841 --- /dev/null +++ b/test/snapshot/selfreference.test.js @@ -0,0 +1,31 @@ +const parser = require("../main"); + +describe("selfreference", function () { + it("variable", function () { + expect(parser.parseEval("self::$var;")).toMatchSnapshot(); + }); + it("constant", function () { + expect(parser.parseEval("self::CONSTANT;")).toMatchSnapshot(); + }); + it("call", function () { + expect(parser.parseEval("self::call();")).toMatchSnapshot(); + }); + it("uppercase", function () { + expect(parser.parseEval("SELF::call();")).toMatchSnapshot(); + }); + it("argument", function () { + expect(parser.parseEval("function foo(self $arg) {}")).toMatchSnapshot(); + }); + it("argument (uppercase)", function () { + expect(parser.parseEval("function foo(SELF $arg) {}")).toMatchSnapshot(); + }); + it("return type declarations", function () { + expect(parser.parseEval("function foo($arg): self {}")).toMatchSnapshot(); + }); + it("return type declarations (uppercase)", function () { + expect(parser.parseEval("function foo($arg): SELF {}")).toMatchSnapshot(); + }); + it("return static type declarations", function () { + expect(parser.parseEval("function foo($arg): static {}")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/silent.test.js b/test/snapshot/silent.test.js new file mode 100644 index 000000000..3386b4388 --- /dev/null +++ b/test/snapshot/silent.test.js @@ -0,0 +1,7 @@ +const parser = require("../main"); + +describe("silent", function () { + it("simple", function () { + expect(parser.parseEval("@call();")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/statement.test.js b/test/snapshot/statement.test.js new file mode 100644 index 000000000..6f4128d90 --- /dev/null +++ b/test/snapshot/statement.test.js @@ -0,0 +1,145 @@ +const parser = require("../main"); + +describe("Test statements", function () { + it("test goto label", function () { + expect( + parser.parseEval(` + start: + $i++; + goto start; + `), + ).toMatchSnapshot(); + }); + + it("test global", function () { + expect( + parser.parseEval(` + function foo() { + global $a, $b; + } + `), + ).toMatchSnapshot(); + }); + + describe("halt statements", function () { + it("test halt statement", function () { + expect( + parser.parseEval( + ` + $a = 1; + __halt_compiler(); + $b = 1; + `, + { + parser: { debug: false }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test inner error", function () { + expect(() => { + parser.parseEval(` + if (true) { + __halt_compiler(); + } + `); + }).toThrow(); + }); + + it("test fallback", function () { + expect( + parser.parseEval( + ` + if (true) { + __halt_compiler(); + } + $b = 1; + `, + { + parser: { suppressErrors: true }, + }, + ), + ).toMatchSnapshot(); + }); + }); + + it("test static", function () { + expect( + parser.parseEval( + ` + function foo() { + static $a, $b = 5; + } + static $sVar1 = 11; + `, + { + parser: { debug: false }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test declare", function () { + expect( + parser.parseEval( + ` + if (true) { declare(ticks=1); } + $a = 1; + declare(ticks=2,encoding=ISO-8859-1); + $b = 1; + declare(ticks=1) { + $c = 2; + } + declare(encoding="UTF-8"): + $d = 3; + enddeclare; + $e = 4; + `, + { + parser: { debug: false }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test try", function () { + expect( + parser.parseEval( + ` + try { + foo(); + } catch(FooError|BarError $err) { + var_dump($err); + throw $err; + } finally { + clean(); + } + `, + { + parser: { debug: false }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test inner statements", function () { + expect( + parser.parseEval( + ` + if (true) { + function foo() {} + abstract class foo {} + final class foo {} + class foo {} + trait foo {} + interface foo {} + } + `, + { + parser: { debug: false }, + }, + ), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/static.test.js b/test/snapshot/static.test.js new file mode 100644 index 000000000..553954444 --- /dev/null +++ b/test/snapshot/static.test.js @@ -0,0 +1,15 @@ +const parser = require("../main"); + +describe("static", function () { + it("simple", function () { + expect(parser.parseEval("static $foo;")).toMatchSnapshot(); + }); + it("assign", function () { + expect(parser.parseEval("static $foo = 1;")).toMatchSnapshot(); + }); + it("multiple", function () { + expect( + parser.parseEval("static $foo = 1, $bar = 2, $baz = 3;"), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/staticlookup.test.js b/test/snapshot/staticlookup.test.js new file mode 100644 index 000000000..b43af8a32 --- /dev/null +++ b/test/snapshot/staticlookup.test.js @@ -0,0 +1,22 @@ +const parser = require("../main"); + +describe("staticlookup", function () { + it("simple", function () { + expect(parser.parseEval("Foo::$var;")).toMatchSnapshot(); + }); + it("simple (2)", function () { + expect(parser.parseEval("$var::$var;")).toMatchSnapshot(); + }); + it("call", function () { + expect(parser.parseEval("Foo::call();")).toMatchSnapshot(); + }); + it("call (2)", function () { + expect(parser.parseEval("$var::call();")).toMatchSnapshot(); + }); + it("multiple", function () { + expect(parser.parseEval("$var::$var_1::$var_2;")).toMatchSnapshot(); + }); + it("multiple (2)", function () { + expect(parser.parseEval("Foo::$var_1::$var_2;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/staticreference.test.js b/test/snapshot/staticreference.test.js new file mode 100644 index 000000000..8c720e893 --- /dev/null +++ b/test/snapshot/staticreference.test.js @@ -0,0 +1,16 @@ +const parser = require("../main"); + +describe("staticreference", function () { + it("variable", function () { + expect(parser.parseEval("static::$var;")).toMatchSnapshot(); + }); + it("constant", function () { + expect(parser.parseEval("static::CONSTANT;")).toMatchSnapshot(); + }); + it("call", function () { + expect(parser.parseEval("static::call();")).toMatchSnapshot(); + }); + it("uppercase", function () { + expect(parser.parseEval("STATIC::call();")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/string.test.js b/test/snapshot/string.test.js new file mode 100644 index 000000000..20d876177 --- /dev/null +++ b/test/snapshot/string.test.js @@ -0,0 +1,402 @@ +const parser = require("../main"); + +describe("Test strings", function () { + it("fix #251", function () { + expect( + parser.parseEval("$var = \"string ${juices['FOO']} string\";"), + ).toMatchSnapshot(); + }); + + it("fix #144", function () { + expect(parser.parseEval('"encapsed \\" {$var}";')).toMatchSnapshot(); + }); + + describe("fix #101", function () { + it("case 1", function () { + expect(parser.parseEval('"encapsed {$var}";')).toMatchSnapshot(); + }); + + it("case 2", function () { + expect(parser.parseEval('"encapsed {$arr[0]}";')).toMatchSnapshot(); + }); + + it("case 3", function () { + expect(parser.parseEval('"encapsed ${var}";')).toMatchSnapshot(); + }); + }); + + it("fix #124", function () { + expect( + parser.parseEval('$string = "He drank some $juices[koolaid1] juice.";'), + ).toMatchSnapshot(); + }); + + it("fix #123", function () { + expect( + parser.parseEval( + "$string = 'Avoid converting \n chars, but \\' or \\\\ is ok.';", + ), + ).toMatchSnapshot(); + }); + + it("implement #116", function () { + expect(parser.parseEval(`$a = "foo\\nbar";`)).toMatchSnapshot(); + }); + + it("fix #149", function () { + expect(parser.parseEval(`$a = b"foo\\nbar";`)).toMatchSnapshot(); + }); + + it("test binary with double quotes", function () { + expect( + parser.parseEval(`echo b"\\colors contains >$colors<\\n";`), + ).toMatchSnapshot(); + }); + + describe("check infinite on $", function () { + it("using doublequotes", function () { + expect( + parser.parseEval(`echo "$`, { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + + it("using backquotes", function () { + expect( + parser.parseEval("echo `$", { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + + it("with arrow", function () { + expect( + parser.parseEval("echo ` -> $", { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + }); + + describe("check infinite on {", function () { + it("using doublequotes", function () { + expect( + parser.parseEval(`echo "{`, { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + + it("using backquotes", function () { + expect( + parser.parseEval("echo `{", { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + + it("with arrow", function () { + expect( + parser.parseEval("echo ` -> {", { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + }); + + describe("check infinite on ${", function () { + it("using doublequotes", function () { + expect( + parser.parseEval('echo "${', { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + + it("using backquotes", function () { + expect( + parser.parseEval("echo `${", { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + + it("with arrow", function () { + expect( + parser.parseEval("echo ` -> ${", { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + }); + + describe("check infinite on {$", function () { + it("using doublequotes", function () { + expect( + parser.parseEval('echo "{$', { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + + it("using backquotes", function () { + expect( + parser.parseEval("echo `{$", { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + + it("with arrow", function () { + expect( + parser.parseEval("echo ` -> {$", { + parser: { suppressErrors: true, debug: false }, + lexer: { debug: false }, + }), + ).toMatchSnapshot(); + }); + }); + + it.skip("binary cast", function () { + expect( + parser.parseEval(`echo (binary)"\\colors[1] contains >$colors[1]<\\n";`), + ).toMatchSnapshot(); + }); + + it("test encapsed variable", function () { + expect( + parser.parseEval(` + echo "Hello $obj->name !"; + echo "Hello $obj->foo->bar !"; + echo "Hello $obj[1]->foo !"; + `), + ).toMatchSnapshot(); + }); + + it("encapsed variable / curly varname", function () { + expect(parser.parseEval('echo "Hello ${obj}->name !";')).toMatchSnapshot(); + }); + + it("encapsed variable / curly constant", function () { + expect(parser.parseEval('echo "Hello ${ obj }";')).toMatchSnapshot(); + }); + + it("encapsed variable / offsetlookup", function () { + expect(parser.parseEval('echo "${$parts[$i]}\\n";')).toMatchSnapshot(); + }); + + it("test double quotes", function () { + expect( + parser.parseEval( + [ + '$a = "$";', + '$a = "{";', + '$a = "-$-";', + '$a = "-{";', + '$a = "$b";', + '$a = "{$b}";', + '$a = "${$b}";', + '$a = "-$b?";', + '$a = "-{$b}";', + '$a = "-${$b}";', + '$a = "";', + '$a = "\\"";', + ].join("\r\n"), + { + lexer: { + debug: false, + }, + parser: { + debug: false, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it.each([ + 'echo B"\\colors[1] contains >$colors[1]<\\n";', + 'echo "\\colors[1] contains >$colors [1]<\\n";', + "echo \"~'.{{$expectedLength}}'\\$~s\";", + "$a = b'\\t\\ra';", + '$foo = array("v1.09azAZ-._~!$", true);', + '$v = strtolower("$i.$j.$k-$rel");', + '$text = "$text at line $line";', + "return \"Class.create('$package$className',{\";", + "echo \"yo : {$feeds[0]['title[0][value]']}\";", + 'return "\\x1B[{$color}m{$str}\\x1B[0m";', + 'echo "\\"$parts[0]\\"\\n";', + 'echo "Hello {".$obj->name."} !";', + 'echo "Hello {$obj->name} !";', + ])("string test: %s", function (code) { + parser.parseEval(code); + }); + + it("test encapsed elements", function () { + expect( + parser.parseEval( + [ + "$code = <<<\t EOFX", + "{$this->docStar}", + "${$foo}", + "${targetDirs[1]}", + "$test[1]", + "$test->foo", + "EOFX;", + ].join("\r"), + { + parser: { + debug: false, + }, + }, + ), + ).toMatchSnapshot(); + }); + + it("test nowdoc label and contents", function () { + expect( + parser.parseEval(["$code .= <<<'EOF'", " }", "EOF;"].join("\r\n"), { + parser: { + debug: false, + }, + }), + ).toMatchSnapshot(); + }); + + it.skip("heredoc ...", function () { + expect( + parser.parseEval(` + $fallbackContent .= sprintf(<<addFallbackCatalogue(\\$catalogue%s); + EOF2 + ) + `), + ).toMatchSnapshot(); + }); + + it("test empty nowdoc & heredoc contents", function () { + expect( + parser.parseEval( + ` + echo << bug throw new Exception("oops");'), + ).toMatchSnapshot(); + }); + it("arrow function in PHP < 8", function () { + expect(() => + parser.parseEval('$fn = fn() => throw new Exception("oops");', { + parser: { version: "7.4" }, + }), + ).toThrow(); + }); +}); diff --git a/test/snapshot/token.test.js b/test/snapshot/token.test.js new file mode 100644 index 000000000..7b9e47538 --- /dev/null +++ b/test/snapshot/token.test.js @@ -0,0 +1,13 @@ +const parser = require("../main"); + +describe("Test tokens statements", function () { + it("hello world", function () { + const ast = parser.parseCode("Hello ", { + parser: { + debug: false, + extractTokens: true, + }, + }); + expect(ast).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/trait.test.js b/test/snapshot/trait.test.js new file mode 100644 index 000000000..a377232f9 --- /dev/null +++ b/test/snapshot/trait.test.js @@ -0,0 +1,7 @@ +const parser = require("../main"); + +describe("trait", function () { + it("trait name as identifier", function () { + expect(parser.parseEval("trait A {}")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/traitprecedence.test.js b/test/snapshot/traitprecedence.test.js new file mode 100644 index 000000000..c2e33a906 --- /dev/null +++ b/test/snapshot/traitprecedence.test.js @@ -0,0 +1,18 @@ +const parser = require("../main"); + +describe("traitprecedence", () => { + it("simple", () => { + expect( + parser.parseEval( + ` +class MyHelloWorld extends Base { + use A, B { + B::smallTalk insteadof A; + A::bigTalk insteadof B; + } +} + `, + ), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/try.test.js b/test/snapshot/try.test.js new file mode 100644 index 000000000..7f6c70371 --- /dev/null +++ b/test/snapshot/try.test.js @@ -0,0 +1,81 @@ +const parser = require("../main"); + +describe("boolean", () => { + it("simple", () => { + expect( + parser.parseEval( + "try { call(); } catch (Exception $e) { do_something(); }", + ), + ).toMatchSnapshot(); + }); + it("without variable", () => { + expect( + parser.parseEval("try { call(); } catch (Exception) { do_something(); }"), + ).toMatchSnapshot(); + }); + it("without variable in PHP < 8", () => { + expect(() => + parser.parseEval( + "try { call(); } catch (Exception) { do_something(); }", + { parser: { version: "7.4" } }, + ), + ).toThrow(SyntaxError); + }); + it("qualified name", () => { + expect( + parser.parseEval( + "try { call(); } catch (Foo\\Exception $e) { do_something(); }", + ), + ).toMatchSnapshot(); + }); + + it("fully qualified name", () => { + expect( + parser.parseEval( + "try { call(); } catch (\\Exception $e) { do_something(); }", + ), + ).toMatchSnapshot(); + }); + it("fully qualified name #2", () => { + expect( + parser.parseEval( + "try { call(); } catch (\\Exception\\Foo $e) { do_something(); }", + ), + ).toMatchSnapshot(); + }); + it("relative name", () => { + expect( + parser.parseEval( + "try { call(); } catch (namespace\\Exception $e) { do_something(); }", + ), + ).toMatchSnapshot(); + }); + it("finally", () => { + expect( + parser.parseEval( + "try { call(); } catch (Exception $e) { do_something(); } finally { do_something_other(); }", + ), + ).toMatchSnapshot(); + }); + it("multiple catch", () => { + expect( + parser.parseEval( + "try { call(); } catch (MyException | MyOtherException $e) { do_something(); }", + ), + ).toMatchSnapshot(); + }); + it("multiple catch without variable", () => { + expect( + parser.parseEval( + "try { call(); } catch (MyException | MyOtherException) { do_something(); }", + ), + ).toMatchSnapshot(); + }); + it("multiple catch #2", () => { + expect( + parser.parseEval( + "try { call(); } catch (MyException | Foo\\Exception | \\Exception | \\Exception\\Foo | namespace\\Exception $e) { do_something(); }", + ), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/typereference.test.js b/test/snapshot/typereference.test.js new file mode 100644 index 000000000..1c7777db9 --- /dev/null +++ b/test/snapshot/typereference.test.js @@ -0,0 +1,144 @@ +const parser = require("../main"); + +describe("typereference", function () { + it("int (argument)", function () { + expect(parser.parseEval("function foo(int $arg) {}")).toMatchSnapshot(); + }); + it("int (argument) (uppercase)", function () { + expect(parser.parseEval("function foo(INT $arg) {}")).toMatchSnapshot(); + }); + it("int (return type declarations)", function () { + expect(parser.parseEval("function foo($arg): int {}")).toMatchSnapshot(); + }); + it("int (return type declarations) (uppercase)", function () { + expect(parser.parseEval("function foo($arg): INT {}")).toMatchSnapshot(); + }); + it("float (argument)", function () { + expect(parser.parseEval("function foo(float $arg) {}")).toMatchSnapshot(); + }); + it("float (argument) (uppercase)", function () { + expect(parser.parseEval("function foo(FLOAT $arg) {}")).toMatchSnapshot(); + }); + it("float (return type declarations)", function () { + expect(parser.parseEval("function foo($arg): float {}")).toMatchSnapshot(); + }); + it("float (return type declarations) (uppercase)", function () { + expect(parser.parseEval("function foo($arg): FLOAT {}")).toMatchSnapshot(); + }); + it("bool (argument)", function () { + expect(parser.parseEval("function foo(bool $arg) {}")).toMatchSnapshot(); + }); + it("bool (argument) (uppercase)", function () { + expect(parser.parseEval("function foo(BOOL $arg) {}")).toMatchSnapshot(); + }); + it("bool (return type declarations)", function () { + expect(parser.parseEval("function foo($arg): bool {}")).toMatchSnapshot(); + }); + it("bool (return type declarations) (uppercase)", function () { + expect(parser.parseEval("function foo($arg): BOOL {}")).toMatchSnapshot(); + }); + it("string (argument)", function () { + expect(parser.parseEval("function foo(string $arg) {}")).toMatchSnapshot(); + }); + it("string (argument) (uppercase)", function () { + expect(parser.parseEval("function foo(STRING $arg) {}")).toMatchSnapshot(); + }); + it("string (return type declarations)", function () { + expect(parser.parseEval("function foo($arg): string {}")).toMatchSnapshot(); + }); + it("string (return type declarations) (uppercase)", function () { + expect(parser.parseEval("function foo($arg): STRING {}")).toMatchSnapshot(); + }); + it("array (argument)", function () { + expect(parser.parseEval("function foo(array $arg) {}")).toMatchSnapshot(); + }); + it("array (argument) (uppercase)", function () { + expect(parser.parseEval("function foo(ARRAY $arg) {}")).toMatchSnapshot(); + }); + it("array (return type declarations)", function () { + expect(parser.parseEval("function foo($arg): array {}")).toMatchSnapshot(); + }); + it("array (return type declarations) (uppercase)", function () { + expect(parser.parseEval("function foo($arg): ARRAY {}")).toMatchSnapshot(); + }); + it("callable (argument)", function () { + expect( + parser.parseEval("function foo(callable $arg) {}"), + ).toMatchSnapshot(); + }); + it("callable (argument) (uppercase)", function () { + expect( + parser.parseEval("function foo(CALLABLE $arg) {}"), + ).toMatchSnapshot(); + }); + it("callable (return type declarations)", function () { + expect( + parser.parseEval("function foo($arg): callable {}"), + ).toMatchSnapshot(); + }); + it("callable (return type declarations) (uppercase)", function () { + expect( + parser.parseEval("function foo($arg): CALLABLE {}"), + ).toMatchSnapshot(); + }); + it("object (argument)", function () { + expect(parser.parseEval("function foo(object $arg) {}")).toMatchSnapshot(); + }); + it("object (argument) (uppercase)", function () { + expect(parser.parseEval("function foo(OBJECT $arg) {}")).toMatchSnapshot(); + }); + it("object (return type declarations)", function () { + expect(parser.parseEval("function foo($arg): object {}")).toMatchSnapshot(); + }); + it("object (return type declarations) (uppercase)", function () { + expect(parser.parseEval("function foo($arg): OBJECT {}")).toMatchSnapshot(); + }); + it("iterable (argument)", function () { + expect( + parser.parseEval("function foo(iterable $arg) {}"), + ).toMatchSnapshot(); + }); + it("iterable (argument) (uppercase)", function () { + expect( + parser.parseEval("function foo(ITERABLE $arg) {}"), + ).toMatchSnapshot(); + }); + it("iterable (return type declarations)", function () { + expect( + parser.parseEval("function foo($arg): iterable {}"), + ).toMatchSnapshot(); + }); + it("iterable (return type declarations) (uppercase)", function () { + expect( + parser.parseEval("function foo($arg): ITERABLE {}"), + ).toMatchSnapshot(); + }); + it("void (argument)", function () { + expect(parser.parseEval("function foo(void $arg) {}")).toMatchSnapshot(); + }); + it("void (argument) (uppercase)", function () { + expect(parser.parseEval("function foo(VOID $arg) {}")).toMatchSnapshot(); + }); + it("void (return type declarations)", function () { + expect(parser.parseEval("function foo($arg): void {}")).toMatchSnapshot(); + }); + it("void (return type declarations) (uppercase)", function () { + expect(parser.parseEval("function foo($arg): VOID {}")).toMatchSnapshot(); + }); + it("class", function () { + expect(parser.parseEval("function foo(Foo $arg) {}")).toMatchSnapshot(); + }); + it("class (2)", function () { + expect( + parser.parseEval("function foo(Foo\\Foo $arg) {}"), + ).toMatchSnapshot(); + }); + it("class (3)", function () { + expect(parser.parseEval("function foo($arg): Foo {}")).toMatchSnapshot(); + }); + it("class (4)", function () { + expect( + parser.parseEval("function foo($arg): Foo\\Foo {}"), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/unary.test.js b/test/snapshot/unary.test.js new file mode 100644 index 000000000..d1d992851 --- /dev/null +++ b/test/snapshot/unary.test.js @@ -0,0 +1,34 @@ +const parser = require("../main"); + +describe("Test unary", function () { + it.each([ + ["simple", "!$var;"], + ["number", "-100;"], + ["number (2)", "+100;"], + ["number (3)", "~100;"], + ["number (4)", "!100;"], + ["string", '+"string";'], + ["string (2)", '-"string";'], + ["string (3)", '~"string";'], + ["string (4)", '!"string";'], + ["boolean", "!true;"], + ["multiple", "!!$var;"], + ["multiple", "~~$var;"], + ["multiple (2)", "--$var;"], + ["multiple (3)", "+(+$var);"], + ["multiple (4)", "-(-$var);"], + ["multiple (5)", "!!!!!$var;"], + ["parens", "(!$var);"], + ["parens (2)", "!($var);"], + ["parens (3)", "(-$var);"], + ["parens (4)", "-($var);"], + ["parens (5)", "(+$var);"], + ["parens (6)", "+($var);"], + ["parens (7)", "~($var);"], + ["parens (8)", "(~$var);"], + ["parens (9)", "(-100);"], + ["parens (10)", "-(100);"], + ])("%s", function (_, code) { + expect(parser.parseEval(code)).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/union.test.js b/test/snapshot/union.test.js new file mode 100644 index 000000000..8e54971d0 --- /dev/null +++ b/test/snapshot/union.test.js @@ -0,0 +1,61 @@ +const parser = require("../main"); + +describe("Test unions", function () { + it("simple union", function () { + expect(parser.parseEval("function(foo|bar $test) {}")).toMatchSnapshot(); + }); + + it("simple intersection", function () { + expect(parser.parseEval("function(foo&bar $test) {}")).toMatchSnapshot(); + }); + + it("union with reference", function () { + expect(parser.parseEval("function(foo|bar &$test) {}")).toMatchSnapshot(); + }); + + it("intersection with reference", function () { + expect(parser.parseEval("function(foo&bar &$test) {}")).toMatchSnapshot(); + }); + + it("union with variadic", function () { + expect(parser.parseEval("function(foo|bar ...$test) {}")).toMatchSnapshot(); + }); + + it("intersection with variadic", function () { + expect(parser.parseEval("function(foo&bar ...$test) {}")).toMatchSnapshot(); + }); + + it("union with three types", function () { + expect( + parser.parseEval("function(foo|bar|baz $test) {}"), + ).toMatchSnapshot(); + }); + + it("intersection with three types", function () { + expect( + parser.parseEval("function(foo&bar&baz $test) {}"), + ).toMatchSnapshot(); + }); + + it("union mixed with intersection", function () { + const astErr = parser.parseEval("function(foo|bar&baz $test) {}", { + parser: { + version: "8.1", + suppressErrors: true, + }, + }); + + expect(astErr).toMatchSnapshot(); + }); + + it("intersection mixed with union", function () { + const astErr = parser.parseEval("function(foo&bar|baz $test) {}", { + parser: { + version: "8.1", + suppressErrors: true, + }, + }); + + expect(astErr).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/unset.test.js b/test/snapshot/unset.test.js new file mode 100644 index 000000000..a3e002cee --- /dev/null +++ b/test/snapshot/unset.test.js @@ -0,0 +1,16 @@ +const parser = require("../main"); + +describe("unset", function () { + it("simple", function () { + expect(parser.parseEval("unset($var);")).toMatchSnapshot(); + }); + it("multiple", function () { + expect(parser.parseEval("unset($var, $var, $var);")).toMatchSnapshot(); + }); + it("trailing comma", function () { + expect(parser.parseEval("unset($foo,);")).toMatchSnapshot(); + }); + it("trailing comma #2", function () { + expect(parser.parseEval("unset($foo, $bar,);")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/usegroup.test.js b/test/snapshot/usegroup.test.js new file mode 100644 index 000000000..5cedc5096 --- /dev/null +++ b/test/snapshot/usegroup.test.js @@ -0,0 +1,50 @@ +const parser = require("../main"); + +describe("usegroup", () => { + it("simple", () => { + expect( + parser.parseEval("use My\\Full\\Classname as Another;"), + ).toMatchSnapshot(); + }); + it("multiple", () => { + expect( + parser.parseEval("use My\\Full\\Classname as Another, My\\Full\\NSname;"), + ).toMatchSnapshot(); + }); + it("multiple 2", () => { + expect( + parser.parseEval( + "use My\\Full\\Classname as Another, My\\Full\\NSname, \\Full\\NSname\\With\\Leading\\Backslash;", + ), + ).toMatchSnapshot(); + }); + it("nested", () => { + expect( + parser.parseEval( + "use some\\my_namespace\\{ClassA, ClassB, ClassC as C};", + ), + ).toMatchSnapshot(); + }); + it("nested 2", () => { + expect( + parser.parseEval("use function some\\my_namespace\\{fn_a, fn_b, fn_c};"), + ).toMatchSnapshot(); + }); + it("nested 3", () => { + expect( + parser.parseEval( + "use const some\\my_namespace\\{ConstA, ConstB, ConstC};", + ), + ).toMatchSnapshot(); + }); + it("nested 4", () => { + expect( + parser.parseEval( + `use Vendor\\Package\\SomeNamespace\\{ + SubnamespaceOne\\ClassA, + SubnamespaceOne\\ClassB + };`, + ), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/useitem.test.js b/test/snapshot/useitem.test.js new file mode 100644 index 000000000..bdb931da8 --- /dev/null +++ b/test/snapshot/useitem.test.js @@ -0,0 +1,62 @@ +const parser = require("../main"); + +describe("useitem", () => { + it("simple", () => { + expect(parser.parseEval("use My\\Full\\NSname;")).toMatchSnapshot(); + }); + it("simple 2", () => { + expect(parser.parseEval("use ArrayObject;")).toMatchSnapshot(); + }); + it("with type", () => { + expect( + parser.parseEval("use My\\Full\\Classname as Another;"), + ).toMatchSnapshot(); + }); + it("importing a function", () => { + expect( + parser.parseEval("use function My\\Full\\functionName;"), + ).toMatchSnapshot(); + }); + it("importing a function with type", () => { + expect( + parser.parseEval("use function My\\Full\\functionName as func;"), + ).toMatchSnapshot(); + }); + it("importing a class", () => { + expect( + parser.parseEval("use some\\my_namespace\\ClassC;"), + ).toMatchSnapshot(); + }); + it("importing a class with type", () => { + expect( + parser.parseEval("use some\\my_namespace\\ClassC as C;"), + ).toMatchSnapshot(); + }); + it("importing a constant", () => { + expect(parser.parseEval("use const My\\Full\\CONSTANT;")).toMatchSnapshot(); + }); + it("importing a constant with type", () => { + expect( + parser.parseEval("use const My\\Full\\CONSTANT as MY_CONST;"), + ).toMatchSnapshot(); + }); + it("invalid use", () => { + expect( + parser.parseEval( + `use function $foo; + use const namespace\\{ + FOO, + BAR, + }; + use some\\{ + namespace\\foo, + $error, + function $bar, + };`, + { + parser: { suppressErrors: true }, + }, + ), + ).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/variable.test.js b/test/snapshot/variable.test.js new file mode 100644 index 000000000..dff819c9b --- /dev/null +++ b/test/snapshot/variable.test.js @@ -0,0 +1,182 @@ +const parser = require("../main"); + +describe("Test variables", function () { + it("fix 253 - can't be parsed `global` with multiple `$`", function () { + expect( + parser.parseEval(` + global $$foo; + `), + ).toMatchSnapshot(); + }); + + it("fix 248 - broken ast for `$$$$$`", function () { + expect( + parser.parseEval(` + $foo::$$property; + $foo::\${$property}; + $bar->$$property; + $bar->\${$property}; + `), + ).toMatchSnapshot(); + }); + + it("fix 248 - test curly", function () { + expect( + parser.parseEval(` + $bar->{$property->foo}; + $bar->\${$property}; + $bar->foo_{$property}; + `), + ).toMatchSnapshot(); + }); + + it("array destructuring", function () { + expect(parser.parseEval("[$id1, $name1] = $data[0];")).toMatchSnapshot(); + }); + + it("default variables", function () { + expect( + parser.parseEval(` + $a = "foo"; + $b = &$c; + $a->b = true;`), + ).toMatchSnapshot(); + }); + + it("Variable chains", function () { + expect(parser.parseEval("foo::$a[1][2];")).toMatchSnapshot(); + }); + + it("fix #167", function () { + expect( + parser.parseEval("$var = Foo::{$bar['baz']}();Foo::$bar['baz']();"), + ).toMatchSnapshot(); + }); + + it("valid offset lookup", function () { + expect( + parser.parseEval("get_class($var)::$$$$$property;"), + ).toMatchSnapshot(); + }); + + it("fix #185", function () { + expect( + parser.parseEval(` + $var = ($var[0])::foo; + $var = ($var[0][1])::foo; + $var = ($var[0])[1]::foo; + $var = (($var[0])[1])::foo; + $var = (new Foo())::bar; + get_class($this->resource)::$wrap; + `), + ).toMatchSnapshot(); + }); + + it("Class constants", function () { + expect( + parser.parseEval(` + static::foo(); + self::foo(); + parent::foo(); + foo::class; + $this->foo(); + foo::$bar; + $this->foo::bar["baz"]::qux();`), + ).toMatchSnapshot(); + }); + + it("Encaps var offset", function () { + expect( + parser.parseEval(` + $a = "{$a[1]}"; + $a = "{$a["a"]}"; + $a = "{$a[$b]}";`), + ).toMatchSnapshot(); + }); + + it("Chained encapsed vars", function () { + expect( + parser.parseEval( + ` + $a = "{$a->foo()[$bar[$foo]]}"; + `, + ), + ).toMatchSnapshot(); + }); + + it("Dynamic variables", function () { + expect( + parser.parseEval(` + $$a = "bar"; + $$$a = "bar"; + \${$a."bar"} = "bar"; + $foo{$a."bar"} = "bar"; + `), + ).toMatchSnapshot(); + }); + + describe("Check errors", function () { + it("should be ?", function () { + expect( + parser.parseEval("$? = true;", { + parser: { + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + }); + + it("should fail on double static lookup", function () { + expect( + parser.parseEval(["this->foo::bar::baz;"].join("\n"), { + parser: { + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + }); + + it("should fail on property lookup on static lookup", function () { + expect( + parser.parseEval(["$this->foo::bar->baz;"].join("\n"), { + parser: { + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + }); + + it("should fail $foo->bar::!", function () { + expect( + parser.parseEval("$foo->bar::!", { + parser: { + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + }); + + it("should fail foo::bar::baz", function () { + expect( + parser.parseEval("foo::bar::baz", { + parser: { + suppressErrors: true, + }, + }), + ).toMatchSnapshot(); + }); + }); + + it("simple variable", function () { + expect(parser.parseEval("$var = $var;")).toMatchSnapshot(); + }); + it("simple variable #2", function () { + expect(parser.parseEval("$var = ${$var};")).toMatchSnapshot(); + }); + it("simple variable #3", function () { + expect(parser.parseEval("$var = ${$var + 'foo'};")).toMatchSnapshot(); + }); + it("simple variable #4", function () { + expect(parser.parseEval("$var = $$$var;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/yield.test.js b/test/snapshot/yield.test.js new file mode 100644 index 000000000..4b82a19e5 --- /dev/null +++ b/test/snapshot/yield.test.js @@ -0,0 +1,32 @@ +const parser = require("../main"); + +describe("yield", function () { + it("simple", function () { + expect(parser.parseEval("yield $i;")).toMatchSnapshot(); + }); + it("assign", function () { + expect(parser.parseEval("$data = yield $value;")).toMatchSnapshot(); + }); + it("assign (parens)", function () { + expect(parser.parseEval("$data = (yield $value);")).toMatchSnapshot(); + }); + it("simple (key and value)", function () { + expect(parser.parseEval("yield $id => $fields;")).toMatchSnapshot(); + }); + it("assign (key and value)", function () { + expect( + parser.parseEval("$data = (yield $key => $value);"), + ).toMatchSnapshot(); + }); + it("inside function", function () { + expect(parser.parseEval("function foo() { yield $i; }")).toMatchSnapshot(); + }); + it("expression as generator key", function () { + expect( + parser.parseEval('function foo() { yield "bar {$test}" => 123; }'), + ).toMatchSnapshot(); + }); + it("null", function () { + expect(parser.parseEval("yield;")).toMatchSnapshot(); + }); +}); diff --git a/test/snapshot/yieldfrom.test.js b/test/snapshot/yieldfrom.test.js new file mode 100644 index 000000000..f7480feb9 --- /dev/null +++ b/test/snapshot/yieldfrom.test.js @@ -0,0 +1,18 @@ +const parser = require("../main"); + +describe("yieldfrom", function () { + it("simple", function () { + expect(parser.parseEval("yield from from();")).toMatchSnapshot(); + }); + it("array", function () { + expect(parser.parseEval("yield from [3, 4];")).toMatchSnapshot(); + }); + it("new", function () { + expect( + parser.parseEval("yield from new ArrayIterator([5, 6]);"), + ).toMatchSnapshot(); + }); + it("return", function () { + expect(parser.parseEval("return yield from nine_ten();")).toMatchSnapshot(); + }); +}); diff --git a/test/statementTests.js b/test/statementTests.js deleted file mode 100644 index a0218f06a..000000000 --- a/test/statementTests.js +++ /dev/null @@ -1,212 +0,0 @@ -var should = require("should"); -var parser = require('../src/index'); - -describe('Test statements', function() { - it('test goto label', function() { - var ast = parser.parseEval([ - 'start:', - ' $i++;', - 'goto start;' - ].join('\n'), { - parser: { debug: false } - }); - ast.children[0].kind.should.be.exactly('label'); - ast.children[0].name.should.be.exactly('start'); - ast.children[1].kind.should.be.exactly('post'); - ast.children[2].kind.should.be.exactly('goto'); - ast.children[2].label.should.be.exactly('start'); - }); - - it('test global', function() { - var ast = parser.parseEval([ - 'function foo() {', - ' global $a, $b;', - '}' - ].join('\n'), { - parser: { debug: false } - }); - var expr = ast.children[0].body.children[0]; - expr.kind.should.be.exactly('global'); - expr.items[0].kind.should.be.exactly('variable'); - expr.items[0].name.should.be.exactly('a'); - expr.items[1].kind.should.be.exactly('variable'); - expr.items[1].name.should.be.exactly('b'); - }); - - it('test halt statement', function() { - var ast = parser.parseEval([ - '$a = 1;', - '__halt_compiler();', - '$b = 1;' - ].join('\n'), { - parser: { debug: false } - }); - ast.children.length.should.be.exactly(2); - ast.children[0].kind.should.be.exactly('assign'); - ast.children[1].kind.should.be.exactly('halt'); - ast.children[1].after.should.be.exactly('\n$b = 1;'); - - // test the inner error - (function() { - var ast = parser.parseEval([ - 'if (true) {', - ' __halt_compiler();', - '}' - ].join('\n')); - }).should.throw(/line\s2/); - - // test the fallback - ast = parser.parseEval([ - 'if (true) {', - ' __halt_compiler();', - '}', - '$b = 1;' - ].join('\n'), { - parser: { suppressErrors: true } - }); - - ast.children.length.should.be.exactly(2); - ast.errors.length.should.be.exactly(1); - ast.children[0].kind.should.be.exactly('if'); - ast.children[0].body.children[0].kind.should.be.exactly('halt'); - ast.children[0].body.children[0].after.should.be.exactly('\n}\n$b = 1;'); - ast.children[1].kind.should.be.exactly('assign'); - - }); - - it('test static', function() { - var ast = parser.parseEval([ - 'function foo() {', - ' static $a, $b = 5;', - '}', - 'static $sVar1 = 11;' - ].join('\n'), { - parser: { debug: false } - }); - - // test function multi statements - var expr = ast.children[0].body.children[0]; - expr.kind.should.be.exactly('static'); - expr.items.length.should.be.exactly(2); - expr.items[0].kind.should.be.exactly('variable'); - expr.items[1].kind.should.be.exactly('assign'); - - // test single statement - ast.children[1].kind.should.be.exactly('static'); - ast.children[1].items.length.should.be.exactly(1); - ast.children[1].items[0].kind.should.be.exactly('assign'); - ast.children[1].items[0].left.kind.should.be.exactly('variable'); - ast.children[1].items[0].left.name.should.be.exactly('sVar1'); - ast.children[1].items[0].right.kind.should.be.exactly('number'); - ast.children[1].items[0].right.value.should.be.exactly('11'); - - }); - - it('test declare', function() { - var ast = parser.parseEval([ - 'declare(ticks=1);', - '$a = 1;', - 'declare(ticks=2,encoding="ISO-8859-1");', - '$b = 1;', - 'declare(ticks=1) {', - ' $c = 2;', - '}', - 'declare(encoding="UTF-8"):', - ' $d = 3;', - 'enddeclare;', - '$e = 4;' // <- single statement - ].join('\n'), { - parser: { debug: false } - }); - ast.children.length.should.be.exactly(5); - - ast.children[0].kind.should.be.exactly('declare'); - ast.children[0].mode.should.be.exactly('none'); - ast.children[0].children.length.should.be.exactly(1); - ast.children[0].children[0].left.name.should.be.exactly('a'); - ast.children[0].what.ticks.kind.should.be.exactly('number'); - ast.children[0].what.ticks.value.should.be.exactly('1'); - - ast.children[1].kind.should.be.exactly('declare'); - ast.children[1].mode.should.be.exactly('none'); - ast.children[1].children.length.should.be.exactly(1); - ast.children[1].children[0].left.name.should.be.exactly('b'); - ast.children[1].what.ticks.kind.should.be.exactly('number'); - ast.children[1].what.ticks.value.should.be.exactly('2'); - ast.children[1].what.encoding.kind.should.be.exactly('string'); - ast.children[1].what.encoding.value.should.be.exactly('ISO-8859-1'); - - ast.children[2].kind.should.be.exactly('declare'); - ast.children[2].mode.should.be.exactly('block'); - ast.children[2].children.length.should.be.exactly(1); - ast.children[2].children[0].left.name.should.be.exactly('c'); - ast.children[2].what.ticks.kind.should.be.exactly('number'); - ast.children[2].what.ticks.value.should.be.exactly('1'); - - ast.children[3].kind.should.be.exactly('declare'); - ast.children[3].mode.should.be.exactly('short'); - ast.children[3].children.length.should.be.exactly(1); - ast.children[3].children[0].left.name.should.be.exactly('d'); - ast.children[3].what.encoding.kind.should.be.exactly('string'); - ast.children[3].what.encoding.value.should.be.exactly('UTF-8'); - - ast.children[4].kind.should.be.exactly('assign'); - }); - - it('test try', function() { - var ast = parser.parseEval([ - 'try {', - ' foo();', - '} catch(FooError|BarError $err) {', - ' var_dump($err);', - ' throw $err;', - '} finally {', - ' clean();', - '}' - ].join('\n'), { - parser: { debug: false } - }); - - var expr = ast.children[0]; - expr.kind.should.be.exactly('try'); - expr.body.kind.should.be.exactly('block'); - expr.body.children[0].kind.should.be.exactly('call'); - expr.body.children[0].what.name.should.be.exactly('foo'); - expr.catches.length.should.be.exactly(1); - - // test catch - var catchExpr = expr.catches[0]; - catchExpr.kind.should.be.exactly('catch'); - catchExpr.what.length.should.be.exactly(2); - catchExpr.what[0].name.should.be.exactly('FooError'); - catchExpr.what[1].name.should.be.exactly('BarError'); - catchExpr.variable.kind.should.be.exactly('variable'); - catchExpr.variable.name.should.be.exactly('err'); - - // test the throw statement - catchExpr.body.kind.should.be.exactly('block'); - catchExpr.body.children.length.should.be.exactly(2); - catchExpr.body.children[1].kind.should.be.exactly('throw'); - catchExpr.body.children[1].what.kind.should.be.exactly('variable'); - catchExpr.body.children[1].what.name.should.be.exactly('err'); - - // always block - expr.always.kind.should.be.exactly('block'); - }); - - it('test inner statements', function() { - var ast = parser.parseEval([ - 'if (true) {', - ' function foo() {}', - ' abstract class foo {}', - ' final class foo {}', - ' class foo {}', - ' trait foo {}', - ' interface foo {}', - '}' - ].join('\n'), { - parser: { debug: false } - }); - // @todo : do assert - }); -}); diff --git a/test/stringTests.js b/test/stringTests.js deleted file mode 100644 index 0d5aa33e9..000000000 --- a/test/stringTests.js +++ /dev/null @@ -1,269 +0,0 @@ -var should = require("should"); -var parser = require('../src/index'); - -describe('Test strings', function() { - - it('...', function() { - var ast = parser.parseEval('$a = b\'\\t\\ra\';'); - }); - it('...', function() { - var ast = parser.parseEval('echo b"\\colors contains >$colors<\\n";'); - }); - it('...', function() { - var ast = parser.parseEval('echo B"\\colors[1] contains >$colors[1]<\\n";'); - }); - it('binary cast', function() { - var ast = parser.parseEval('echo (binary)"\\colors[1] contains >$colors[1]<\\n";'); - // @todo console.log(ast.children[0].arguments[0]); - }); - it('...', function() { - var ast = parser.parseEval('echo "\\colors[1] contains >$colors [1]<\\n";'); - }); - it('...', function() { - var ast = parser.parseEval('echo "~\'.{{$expectedLength}}\'\\$~s";'); - }); - it('test encapsed variable', function() { - var ast = parser.parseEval([ - 'echo "Hello $obj->name !";', - 'echo "Hello $obj->foo->bar !";', - 'echo "Hello $obj[1]->foo !";' - ].join('\n')); - - ast.children[0].arguments[0].kind.should.be.exactly('encapsed'); - ast.children[0].arguments[0].value[0].value.should.be.exactly('Hello '); - ast.children[0].arguments[0].value[2].value.should.be.exactly(' !'); - - ast.children[1].arguments[0].kind.should.be.exactly('encapsed'); - ast.children[1].arguments[0].value[0].value.should.be.exactly('Hello '); - ast.children[1].arguments[0].value[2].value.should.be.exactly('->bar !'); - - ast.children[2].arguments[0].kind.should.be.exactly('encapsed'); - ast.children[2].arguments[0].value[0].value.should.be.exactly('Hello '); - ast.children[2].arguments[0].value[2].value.should.be.exactly('->foo !'); - }); - it('...', function() { - var ast = parser.parseEval('echo "Hello {".$obj->name."} !";'); - }); - it('...', function() { - var ast = parser.parseEval('echo "Hello {$obj->name} !";'); - }); - it('Encapsed variable / curly varname', function() { - var ast = parser.parseEval('echo "Hello ${obj}->name !";'); - ast.children[0].kind.should.be.exactly('echo'); - ast.children[0].arguments.length.should.be.exactly(1); - var arg1 = ast.children[0].arguments[0]; - arg1.kind.should.be.exactly('encapsed'); - arg1.type.should.be.exactly('string'); - arg1.value.length.should.be.exactly(3); - // test constant parts - arg1.value[0].kind.should.be.exactly('string'); - arg1.value[0].value.should.be.exactly('Hello '); - arg1.value[2].kind.should.be.exactly('string'); - arg1.value[2].value.should.be.exactly('->name !'); - // test the varname - arg1.value[1].kind.should.be.exactly('variable'); - arg1.value[1].name.should.be.exactly('obj'); - arg1.value[1].curly.should.be.exactly(true); - }); - it('Encapsed variable / curly constant', function() { - var ast = parser.parseEval('echo "Hello ${ obj }";'); - ast.children[0].kind.should.be.exactly('echo'); - ast.children[0].arguments.length.should.be.exactly(1); - var arg1 = ast.children[0].arguments[0]; - arg1.kind.should.be.exactly('encapsed'); - arg1.type.should.be.exactly('string'); - arg1.value.length.should.be.exactly(2); - // test constant parts - arg1.value[0].kind.should.be.exactly('string'); - arg1.value[0].value.should.be.exactly('Hello '); - // test the varname - arg1.value[1].kind.should.be.exactly('variable'); - arg1.value[1].name.kind.should.be.exactly('constref'); - arg1.value[1].name.name.kind.should.be.exactly('identifier'); - arg1.value[1].name.name.name.should.be.exactly('obj'); - arg1.value[1].curly.should.be.exactly(true); - }); - it('...', function() { - var ast = parser.parseEval('echo "\\"$parts[0]\\"\\n";'); - }); - it('Encapsed variable / offsetlookup', function() { - var ast = parser.parseEval('echo "${$parts[$i]}\\n";'); - ast.children[0].kind.should.be.exactly('echo'); - ast.children[0].arguments.length.should.be.exactly(1); - var arg1 = ast.children[0].arguments[0]; - arg1.kind.should.be.exactly('encapsed'); - arg1.type.should.be.exactly('string'); - arg1.value.length.should.be.exactly(2); - // check the varvar - arg1.value[0].kind.should.be.exactly('variable'); - // check the lookup structure - arg1.value[0].name.kind.should.be.exactly('offsetlookup'); - arg1.value[0].name.what.name.should.be.exactly('parts'); - arg1.value[0].name.offset.name.should.be.exactly('i'); - // check ending string - arg1.value[1].kind.should.be.exactly('string'); - arg1.value[1].value.should.be.exactly('\n'); - }); - it('...', function() { - var ast = parser.parseEval('echo "yo : {$feeds[0][\'title[0][value]\']}";'); - }); - it('...', function() { - var ast = parser.parseEval('return "\\x1B[{$color}m{$str}\\x1B[0m";'); - }); - it('test double quotes', function() { - var ast = parser.parseEval([ - '$a = "$";', - '$a = "{";', - '$a = "-$-";', - '$a = "-{";', - '$a = "$b";', - '$a = "{$b}";', - '$a = "${$b}";', - '$a = "-$b?";', - '$a = "-{$b}";', - '$a = "-${$b}";', - '$a = "";', - '$a = "\\"";', - ].join('\r\n'), { - lexer: { - debug: false - }, - parser: { - debug: false - } - }); - }); - it('...', function() { - var ast = parser.parseEval('$foo = array("v1.09azAZ-._~!$", true);'); - }); - it('...', function() { - var ast = parser.parseEval('$v = strtolower("$i.$j.$k-$rel");'); - }); - it('...', function() { - var ast = parser.parseEval('$text = "$text at line $line";'); - }); - it('...', function() { - var ast = parser.parseEval('return "Class.create(\'$package$className\',{";'); - }); - it('test encapsed elements', function() { - var ast = parser.parseEval([ - '$code = <<<\t EOFX', - '{$this->docStar}', - '${$foo}', - '${targetDirs[1]}', - '$test[1]', - '$test->foo', - 'EOFX;' - ].join('\r'), { - parser: { - debug: false - } - }); - var expr = ast.children[0].right.value; - expr[0].kind.should.be.exactly('propertylookup'); - expr[2].kind.should.be.exactly('variable'); - expr[4].kind.should.be.exactly('variable'); - expr[6].kind.should.be.exactly('offsetlookup'); - expr[8].kind.should.be.exactly('propertylookup'); - // @todo : improve assertions - }); - it('test nowdoc label and contents', function() { - var ast = parser.parseEval([ - '$code .= <<<\'EOF\'', - ' }', - 'EOF;' - ].join('\r\n'), { - parser: { - debug: false - } - }); - var expr = ast.children[0].right; - expr.kind.should.be.exactly('nowdoc'); - expr.label.should.be.exactly('EOF'); - expr.value.should.be.exactly(' }'); - }); - it('heredoc ...', function() { - var ast = parser.parseEval([ - '$fallbackContent .= sprintf(<<addFallbackCatalogue(\\$catalogue%s);', - 'EOF2', - ');', - ].join('\r\n')); - }); - it('test empty nowdoc & heredoc contents', function() { - var ast = parser.parseEval([ - 'echo << bug b = true;' - ].join('\n')); - it('should be $a', function() { - ast.children[0].left.kind.should.be.exactly('variable'); - ast.children[0].left.name.should.be.exactly('a'); - }); - it('should be $c byref', function() { - ast.children[1].right.kind.should.be.exactly('variable'); - ast.children[1].right.name.should.be.exactly('c'); - ast.children[1].right.byref.should.be.exactly(true); - }); - it('should be $a->b', function() { - ast.children[2].left.kind.should.be.exactly('propertylookup'); - ast.children[2].left.what.kind.should.be.exactly('variable'); - ast.children[2].left.what.name.should.be.exactly('a'); - ast.children[2].left.offset.kind.should.be.exactly('constref'); - ast.children[2].left.offset.name.should.be.exactly('b'); - }); - }); - - describe('Variable chains', function() { - var ast = parser.parseEval([ - 'foo::$a[1][2];' - ].join('\n')); - it('should be $a[1][2]', function() { - var expr = ast.children[0].offset; - expr.kind.should.be.exactly('offsetlookup'); - expr.what.kind.should.be.exactly('offsetlookup'); - expr.offset.value.should.be.exactly('2'); - expr.what.what.kind.should.be.exactly('variable'); - expr.what.what.name.should.be.exactly('a'); - expr.what.offset.value.should.be.exactly('1'); - }); - }); - - describe('Class constants', function() { - var ast = parser.parseEval([ - 'static::foo();', - 'self::foo();', - 'parent::foo();', - 'foo::class;', - '$this->foo();', - 'foo::$bar;' - ].join('\n'), { - parser: { - // debug: true - } - }); - it('should be static::foo', function() { - var expr = ast.children[0].what; - expr.kind.should.be.exactly('staticlookup'); - expr.what.kind.should.be.exactly('constref'); - expr.what.name.should.be.exactly('static'); - expr.offset.kind.should.be.exactly('constref'); - expr.offset.name.should.be.exactly('foo'); - }); - it('should be self::foo', function() { - var expr = ast.children[1].what; - expr.kind.should.be.exactly('staticlookup'); - // @fixme : self should be a constref - //expr.what.kind.should.be.exactly('constref'); - //expr.what.name.should.be.exactly('self'); - expr.offset.kind.should.be.exactly('constref'); - expr.offset.name.should.be.exactly('foo'); - }); - it('should be parent::foo', function() { - var expr = ast.children[2].what; - expr.kind.should.be.exactly('staticlookup'); - // @fixme : parent should be a constref - //expr.what.kind.should.be.exactly('constref'); - //expr.what.name.should.be.exactly('parent'); - expr.offset.kind.should.be.exactly('constref'); - expr.offset.name.should.be.exactly('foo'); - }); - it('should be foo::class', function() { - var expr = ast.children[3]; - expr.kind.should.be.exactly('staticlookup'); - expr.what.kind.should.be.exactly('identifier'); - expr.what.name.should.be.exactly('foo'); - expr.offset.kind.should.be.exactly('constref'); - expr.offset.name.should.be.exactly('class'); - }); - it('should be $this->foo()', function() { - var expr = ast.children[4].what; - expr.kind.should.be.exactly('propertylookup'); - expr.what.kind.should.be.exactly('variable'); - expr.what.name.should.be.exactly('this'); - expr.offset.kind.should.be.exactly('constref'); - expr.offset.name.should.be.exactly('foo'); - }); - it('should be foo::$bar', function() { - var expr = ast.children[5]; - expr.kind.should.be.exactly('staticlookup'); - expr.what.kind.should.be.exactly('identifier'); - expr.what.name.should.be.exactly('foo'); - expr.offset.kind.should.be.exactly('variable'); - expr.offset.name.should.be.exactly('bar'); - }); - }); - - - describe('Encaps var offset', function() { - var ast = parser.parseEval([ - '$a = "{$a[1]}";', - '$a = "{$a["a"]}";', - '$a = "{$a[$b]}";', - ].join('\n')); - it('should be $a[1]', function() { - //console.log(ast.children[0].right); - //ast.children[0].left.kind.should.be.exactly('variable'); - }); - }); - - describe('Dynamic variables', function() { - var ast = parser.parseEval([ - '$$a = "bar";', - '$$$a = "bar";', - '${$a."bar"} = "bar";', - '$foo{$a."bar"} = "bar";' - ].join('\n')); - it('should be $$a', function() { - ast.children[0].left.kind.should.be.exactly('variable'); - ast.children[0].left.name.kind.should.be.exactly('variable'); - ast.children[0].left.name.name.should.be.exactly('a'); - }); - it('should be $$$a', function() { - ast.children[1].left.kind.should.be.exactly('variable'); - ast.children[1].left.name.kind.should.be.exactly('variable'); - ast.children[1].left.name.name.kind.should.be.exactly('variable'); - }); - it('should be ${$a."bar"}', function() { - ast.children[2].left.kind.should.be.exactly('variable'); - ast.children[2].left.name.kind.should.be.exactly('bin'); - ast.children[2].left.name.type.should.be.exactly('.'); - ast.children[2].left.name.left.kind.should.be.exactly('variable'); - ast.children[2].left.name.left.name.should.be.exactly('a'); - ast.children[2].left.name.right.kind.should.be.exactly('string'); - ast.children[2].left.name.right.value.should.be.exactly('bar'); - }); - it('should be $foo{$a."bar"}', function() { - //console.log(ast.children[3]); - //ast.children[3].kind.should.be.exactly('variable'); - }); - }); - - describe('Check errors', function() { - var ast = parser.parseEval([ - '$? = true;' - ].join('\n'), { - parser: { - suppressErrors: true - } - }); - it('should be ?', function() { - ast.children[0].left.kind.should.be.exactly('variable'); - ast.children[0].left.name.should.be.exactly('?'); - }); - }); -}); diff --git a/test/version.test.js b/test/version.test.js new file mode 100644 index 000000000..9d82d1e45 --- /dev/null +++ b/test/version.test.js @@ -0,0 +1,54 @@ +const parser = require("./main"); + +describe("Test versions", function () { + it("unserialize a version string", function () { + const test = parser.create({ + parser: { + version: "7.3", + }, + }); + expect(test.parser.version).toEqual(703); + }); + it("unserialize a version string - with bugfix ignored", function () { + const test = parser.create({ + parser: { + version: "7.3.5", + }, + }); + expect(test.parser.version).toEqual(703); + }); + it("fail to parse array", function () { + expect( + parser.create.bind(null, { + parser: { + version: [701], + }, + }), + ).toThrow(new Error("Expecting a number for version")); + }); + it("fail to parse bad version numbers", function () { + expect( + parser.create.bind(null, { + parser: { + version: "x.y.z", + }, + }), + ).toThrow(new Error("Bad version number : x.y.z")); + }); + it("unhandled version", function () { + expect( + parser.create.bind(null, { + parser: { + version: "4.9", + }, + }), + ).toThrow(new Error("Can only handle versions between 5.x to 8.x")); + expect( + parser.create.bind(null, { + parser: { + version: "9.9", + }, + }), + ).toThrow(new Error("Can only handle versions between 5.x to 8.x")); + }); +}); diff --git a/tutorials/AST.md b/tutorials/AST.md new file mode 100644 index 000000000..147ec4e1a --- /dev/null +++ b/tutorials/AST.md @@ -0,0 +1,135 @@ +# Abstract Syntax Tree + +You can see the AST as a DOM document, the source code of the program beeing +the graphical text output, and the DOM beeing a representation of it. + +The main node is the program node, and it's structured like this : + +```js + { + "kind": "program", + "children": [ + // array of nodes + ] + } +``` + +## Nodes + +Every node has a common structure enabling you to scan them and act accordingly. + +NOTE : This structure depends also on what options you enable. + +```js + { + "kind": "node name", + "loc": { + "" + }, + // the location node + "loc": { + "source": "original source code of the node", + "start": { + "line": 1, // 1 based + "column": 0, // 0 based + "offset": 0 // offset from the source code + }, + "end": { + // same structure as start + } + }, + "leadingComments": [ + // array of comments nodes + ] + } +``` + +## Nodes hierarchy + + - [Location](#location) + - [Position](#position) + - [Node](#node) + - [Identifier](#identifier) + - [TraitUse](#traituse) + - [TraitAlias](#traitalias) + - [TraitPrecedence](#traitprecedence) + - [Entry](#entry) + - [Case](#case) + - [Label](#label) + - [Comment](#comment) + - [CommentLine](#commentline) + - [CommentBlock](#commentblock) + - [Error](#error) + - [Expression](#expression) + - [Array](#array) + - [Variable](#variable) + - [Variadic](#variadic) + - [ConstRef](#constref) + - [Yield](#yield) + - [YieldFrom](#yieldfrom) + - [Lookup](#lookup) + - [PropertyLookup](#propertylookup) + - [StaticLookup](#staticlookup) + - [OffsetLookup](#offsetlookup) + - [Operation](#operation) + - [Pre](#pre) + - [Post](#post) + - [Bin](#bin) + - [Parenthesis](#parenthesis) + - [Unary](#unary) + - [Cast](#cast) + - [Literal](#literal) + - [Boolean](#boolean) + - [String](#string) + - [Number](#number) + - [Inline](#inline) + - [Magic](#magic) + - [Nowdoc](#nowdoc) + - [Encapsed](#encapsed) + - [Statement](#statement) + - [Eval](#eval) + - [Exit](#exit) + - [Halt](#halt) + - [Clone](#clone) + - [Declare](#declare) + - [Global](#global) + - [Static](#static) + - [Include](#include) + - [Assign](#assign) + - [RetIf](#retif) + - [If](#if) + - [Do](#do) + - [While](#while) + - [For](#for) + - [Foreach](#foreach) + - [Switch](#switch) + - [Goto](#goto) + - [Silent](#silent) + - [Try](#try) + - [Catch](#catch) + - [Throw](#throw) + - [Call](#call) + - [Closure](#closure) + - [New](#new) + - [UseGroup](#usegroup) + - [UseItem](#useitem) + - [Block](#block) + - [Program](#program) + - [Namespace](#namespace) + - [Sys](#sys) + - [Echo](#echo) + - [List](#list) + - [Print](#print) + - [Isset](#isset) + - [Unset](#unset) + - [Empty](#empty) + - [Declaration](#declaration) + - [Class](#class) + - [Interface](#interface) + - [Trait](#trait) + - [Constant](#constant) + - [ClassConstant](#classconstant) + - [Function](#function) + - [Method](#method) + - [Parameter](#parameter) + - [Property](#property) \ No newline at end of file diff --git a/docs/README.md b/tutorials/Engine.md similarity index 72% rename from docs/README.md rename to tutorials/Engine.md index 5e0f3e29e..4b91350a1 100644 --- a/docs/README.md +++ b/tutorials/Engine.md @@ -1,7 +1,3 @@ - - -## engine - Initialise a new parser instance with the specified options Usage : @@ -11,7 +7,8 @@ var parser = require('php-parser'); var instance = new parser({ parser: { extractDoc: true, - suppressErrors: true + suppressErrors: true, + php7: true }, ast: { withPositions: true @@ -35,10 +32,10 @@ Type: Engine **Properties** -- `lexer` **Lexer** -- `parser` **Parser** -- `ast` **AST** -- `tokens` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** +- `lexer` **Lexer** +- `parser` **Parser** +- `ast` **AST** +- `tokens` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** ### parseEval @@ -46,9 +43,9 @@ Parse an evaluating mode string (no need to open php tags) **Parameters** -- `buffer` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +- `buffer` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** -Returns **Program** +Returns **Program** ### parseCode @@ -75,7 +72,7 @@ var ast = phpParser.parseCode('...php code...', 'foo.php'); - `buffer` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** The code to be parsed - `filename` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Filename -Returns **Program** +Returns **Program** ### tokenGetAll @@ -85,6 +82,16 @@ Extract tokens from the specified buffer. **Parameters** -- `buffer` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +- `buffer` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)>** Each item can be a string or an array with following informations [token_name, text, line_number] + +## getStringBuffer + +Check if the inpyt is a buffer or a string + +**Parameters** + +- `buffer` **([Buffer](https://nodejs.org/api/buffer.html) \| [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** Input value that can be either a buffer or a string + +Returns **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Returns the string from input diff --git a/tutorials/Options.md b/tutorials/Options.md new file mode 100644 index 000000000..d7b6f02c0 --- /dev/null +++ b/tutorials/Options.md @@ -0,0 +1,41 @@ +# Options + +When you call the parser you can pass options as following : + +```js +var reader = require('php-parser'); +reader.parseCode('` +* short_tags : handle short opening tag ` - -## parser - The PHP Parser class that build the AST tree from the lexer Type: Parser **Parameters** -- `lexer` -- `ast` +* `lexer` +* `ast` **Properties** -- `lexer` **Lexer** current lexer instance -- `ast` **AST** the AST factory instance -- `token` **(Integer | [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** current token -- `extractDoc` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** should extract documentation as AST node -- `suppressErrors` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** should ignore parsing errors and continue -- `debug` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** should output debug informations +* `lexer` **Lexer** current lexer instance +* `ast` **AST** the AST factory instance +* `token` **(Integer | [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String))** current token +* `extractDoc` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** should extract documentation as AST node +* `extractTokens` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** should extract each token +* `suppressErrors` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** should ignore parsing errors and continue +* `debug` **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** should output debug informations ### getTokenName @@ -26,7 +23,7 @@ helper : gets a token name **Parameters** -- `token` +* `token` ### parse @@ -34,8 +31,8 @@ main entry point : converts a source code to AST **Parameters** -- `code` -- `filename` +* `code` +* `filename` ### raiseError @@ -43,10 +40,10 @@ Raise an error **Parameters** -- `message` -- `msgExpect` -- `expect` -- `token` +* `message` +* `msgExpect` +* `expect` +* `token` ### error @@ -54,7 +51,7 @@ handling errors **Parameters** -- `expect` +* `expect` ### node @@ -62,13 +59,13 @@ Creates a new AST node **Parameters** -- `name` +* `name` ### expectEndOfStatement expects an end of statement or end of file -Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** +Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** ### expect @@ -82,30 +79,25 @@ be added to the program error stack and this function will return `false`. **Parameters** -- `token` **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number))** +* `token` **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) \| [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number))** +- Throws **any** Error -- Throws **any** Error - -Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** +Returns **[boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** ### text Returns the current token contents -Returns **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** +Returns **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** ### next consume the next token \* -### ignoreComments - -consume comments (if found) \* +### lex -### nextWithComments - -consume the next token (including doc) \* +Eating a token ### is @@ -113,7 +105,7 @@ Check if token is of specified type **Parameters** -- `type` +* `type` ## ignoreStack @@ -194,9 +186,9 @@ Reads constant list Read member flags Returns **any** array - 1st index : 0 => public, 1 => protected, 2 => private - 2nd index : 0 => instance member, 1 => static member - 3rd index : 0 => normal, 1 => abstract member, 2 => final member +1st index : 0 => public, 1 => protected, 2 => private +2nd index : 0 => instance member, 1 => static member +3rd index : 0 => normal, 1 => abstract member, 2 => final member ## read_interface @@ -238,6 +230,9 @@ Reading trait alias trait_use_alias ::= namespace_name ( T_DOUBLE_COLON T_STRING )? (T_INSTEADOF namespace_name) | (T_AS member_flags? T_STRING) ``` +name list : +trait adaptation : + ## read_variable_declaration Reads a variable declaration @@ -251,7 +246,7 @@ Reads a variable declaration Reads a constant declaration ```ebnf - constant_declaration ::= T_STRING '=' expr + constant_declaration ::= (T_STRING | IDENTIFIER) '=' expr ``` Returns **Constant** [:link:](AST.md#constant) @@ -383,10 +378,6 @@ reads an elseif (expr): statements ## read_else_short -## ignoreComments - -ignore : if (..) { } /\* \*./ else { } - ## read_while Reads a while statement @@ -395,7 +386,7 @@ Reads a while statement while ::= T_WHILE (statement | ':' inner_statement_list T_ENDWHILE ';') ``` -Returns **While** +Returns **While** ## read_do @@ -405,7 +396,7 @@ Reads a do / while loop do ::= T_DO statement T_WHILE '(' expr ')' ';' ``` -Returns **Do** +Returns **Do** ## read_for @@ -417,7 +408,7 @@ for_statement ::= statement | ':' inner_statement_list T_ENDFOR ';' for_exprs ::= expr? (',' expr)* ``` -Returns **For** +Returns **For** ## read_foreach @@ -427,7 +418,7 @@ Reads a foreach loop foreach ::= '(' expr T_AS foreach_variable (T_DOUBLE_ARROW foreach_variable)? ')' statement ``` -Returns **Foreach** +Returns **Foreach** ## read_foreach_variable @@ -439,7 +430,7 @@ foreach_variable = variable | '[' array_pair_list ']' ``` -Returns **Expression** +Returns **Expression** ## read_start @@ -458,7 +449,7 @@ namespace ::= T_NAMESPACE namespace_name? '{' | T_NAMESPACE namespace_name ';' top_statements ``` -Returns **Namespace** +Returns **Namespace** ## read_namespace_name @@ -468,7 +459,7 @@ Reads a namespace name namespace_name ::= T_NS_SEPARATOR? (T_STRING T_NS_SEPARATOR)* T_STRING ``` -Returns **Identifier** +Returns **Identifier** ## read_use_statement @@ -482,7 +473,7 @@ use_statement ::= T_USE ';' ``` -Returns **UseGroup** +Returns **UseGroup** ## read_use_declaration @@ -492,7 +483,7 @@ Reads a use declaration use_declaration ::= use_type? namespace_name use_alias ``` -Returns **UseItem** +Returns **UseItem** ## read_use_declarations @@ -502,7 +493,7 @@ Reads a list of use declarations use_declarations ::= use_declaration (',' use_declaration)* ``` -Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<UseItem>** +Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<UseItem>** ## read_use_alias @@ -512,7 +503,7 @@ Reads a use statement use_alias ::= (T_AS T_STRING)? ``` -Returns **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) | null)** +Returns **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) | null)** ## read_use_type @@ -558,7 +549,7 @@ encapsed_string_item ::= T_ENCAPSED_AND_WHITESPACE | variable T_OBJECT_OPERATOR T_STRING ``` -Returns **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) | Variable | Expr | Lookup)** +Returns **([String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) | Variable | Expr | Lookup)** ## read_encapsed_string @@ -638,7 +629,7 @@ Reads a switch statement switch ::= T_SWITCH '(' expr ')' switch_case_list ``` -Returns **Switch** +Returns **Switch** ## read_switch_case_list @@ -662,7 +653,7 @@ Returns **Switch** (T_FINALLY '{' inner_statement* '}')? ``` -Returns **Try** +Returns **Try** ## read_short_form @@ -670,9 +661,9 @@ Reads a short form of tokens **Parameters** -- `token` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** The ending token +* `token` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** The ending token -Returns **Block** +Returns **Block** ## read_list @@ -696,7 +687,7 @@ Sample code : ** +Returns **[Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)<Identifier>** ## read_variable_declarations diff --git a/types.d.ts b/types.d.ts new file mode 100644 index 000000000..a5ad9c93f --- /dev/null +++ b/types.d.ts @@ -0,0 +1,1447 @@ +declare module "php-parser" { + /** + * Defines an array structure + * @example + * // PHP code : + * [1, 'foo' => 'bar', 3] + * + * // AST structure : + * { + * "kind": "array", + * "shortForm": true + * "items": [ + * {"kind": "number", "value": "1"}, + * { + * "kind": "entry", + * "key": {"kind": "string", "value": "foo", "isDoubleQuote": false}, + * "value": {"kind": "string", "value": "bar", "isDoubleQuote": false} + * }, + * {"kind": "number", "value": "3"} + * ] + * } + * @property items - List of array items + * @property shortForm - Indicate if the short array syntax is used, ex `[]` instead `array()` + */ + class Array extends Expression { + /** + * List of array items + */ + items: (Entry | Expression | Variable)[]; + /** + * Indicate if the short array syntax is used, ex `[]` instead `array()` + */ + shortForm: boolean; + } + /** + * Defines an arrow function (it's like a closure) + */ + class ArrowFunc extends Expression { + arguments: Parameter[]; + type: Identifier; + body: Expression; + byref: boolean; + nullable: boolean; + isStatic: boolean; + } + /** + * Assigns a value to the specified target + */ + class Assign extends Expression { + left: Expression; + right: Expression; + operator: string; + } + /** + * Assigns a value to the specified target + */ + class AssignRef extends Expression { + left: Expression; + right: Expression; + operator: string; + } + /** + * Attribute group + */ + class AttrGroup extends Node { + attrs: Attribute[]; + } + /** + * Attribute Value + */ + class Attribute extends Node { + name: string; + args: Parameter[]; + } + /** + * Binary operations + */ + class Bin extends Operation { + type: string; + left: Expression; + right: Expression; + } + /** + * A block statement, i.e., a sequence of statements surrounded by braces. + */ + class Block extends Statement { + children: Node[]; + } + /** + * Defines a boolean value (true/false) + */ + class Boolean extends Literal { + value: boolean; + } + /** + * A break statement + */ + class Break extends Statement { + level: number | null; + } + /** + * Passing by Reference - so the function can modify the variable + */ + class ByRef extends Expression { + what: ExpressionStatement; + } + /** + * Executes a call statement + */ + class Call extends Expression { + what: Identifier | Variable; + arguments: Expression[]; + } + /** + * A switch case statement + * @property test - if null, means that the default case + */ + class Case extends Statement { + /** + * if null, means that the default case + */ + test: Expression | null; + body: Block | null; + } + /** + * Binary operations + */ + class Cast extends Operation { + type: string; + raw: string; + expr: Expression; + } + /** + * Defines a catch statement + */ + class Catch extends Statement { + what: Name[]; + variable: Variable; + body: Block; + } + /** + * A class definition + */ + class Class extends Declaration { + extends: Identifier | null; + implements: Identifier[] | null; + body: Declaration[]; + isAnonymous: boolean; + isAbstract: boolean; + isFinal: boolean; + isReadonly: boolean; + attrGroups: AttrGroup[]; + } + /** + * Defines a class/interface/trait constant + */ + class ClassConstant extends ConstantStatement { + /** + * Generic flags parser + */ + parseFlags(flags: (number | null)[]): void; + visibility: string; + final: boolean; + nullable: boolean; + type: TypeReference | IntersectionType | UnionType | null; + attrGroups: AttrGroup[]; + } + /** + * Defines a clone call + */ + class Clone extends Expression { + what: Expression; + } + /** + * Defines a closure + */ + class Closure extends Expression { + arguments: Parameter[]; + uses: Variable[]; + type: Identifier; + byref: boolean; + nullable: boolean; + body: Block | null; + isStatic: boolean; + attrGroups: AttrGroup[]; + } + /** + * Abstract documentation node (ComentLine or CommentBlock) + */ + class Comment extends Node { + value: string; + } + /** + * A comment block (multiline) + */ + class CommentBlock extends Comment {} + /** + * A single line comment + */ + class CommentLine extends Comment {} + /** + * Defines a constant + */ + class Constant extends Node { + name: string; + value: Node | string | number | boolean | null; + } + /** + * Declares a constants into the current scope + */ + class ConstantStatement extends Statement { + constants: Constant[]; + } + /** + * A continue statement + */ + class Continue extends Statement { + level: number | null; + } + /** + * A declaration statement (function, class, interface...) + */ + class Declaration extends Statement { + /** + * Generic flags parser + */ + parseFlags(flags: (number | null)[]): void; + name: Identifier | string; + } + /** + * The declare construct is used to set execution directives for a block of code + */ + class Declare extends Block { + /** + * The node is declared as a short tag syntax : + * ```php + * bar_$baz; + * ``` + */ + readonly TYPE_OFFSET: string; + /** + * Defines the type of encapsed string (shell, heredoc, string) + */ + type: string; + /** + * The heredoc label, defined only when the type is heredoc + */ + label: string | null; + value: EncapsedPart[]; + } + /** + * Part of `Encapsed` node + */ + class EncapsedPart extends Expression { + expression: Expression; + syntax: string; + curly: boolean; + } + /** + * An array entry - see [Array](#array) + * @property key - The entry key/offset + * @property value - The entry value + * @property byRef - By reference + * @property unpack - Argument unpacking + */ + class Entry extends Expression { + /** + * The entry key/offset + */ + key: Node | null; + /** + * The entry value + */ + value: Node; + /** + * By reference + */ + byRef: boolean; + /** + * Argument unpacking + */ + unpack: boolean; + } + /** + * A enum definition + */ + class Enum extends Declaration { + valueType: Identifier | null; + implements: Identifier[]; + body: Declaration[]; + attrGroups: AttrGroup[]; + } + /** + * Declares a cases into the current scope + */ + class EnumCase extends Node { + name: string; + value: string | number | null; + } + /** + * Defines an error node (used only on silentMode) + */ + class Error extends Node { + message: string; + line: number; + token: number | string; + expected: string | any[]; + } + /** + * Defines an eval statement + */ + class Eval extends Expression { + source: Node; + } + /** + * Defines an exit / die call + */ + class Exit extends Expression { + expression: Node | null; + useDie: boolean; + } + /** + * Any expression node. Since the left-hand side of an assignment may + * be any expression in general, an expression can also be a pattern. + */ + class Expression extends Node {} + /** + * Defines an expression based statement + */ + class ExpressionStatement extends Statement { + expression: Expression; + } + /** + * Defines a for iterator + */ + class For extends Statement { + init: Expression[]; + test: Expression[]; + increment: Expression[]; + body: Block | null; + shortForm: boolean; + } + /** + * Defines a foreach iterator + */ + class Foreach extends Statement { + source: Expression; + key: Expression | null; + value: Expression; + body: Block | null; + shortForm: boolean; + } + /** + * Defines a classic function + */ + class Function extends Declaration { + arguments: Parameter[]; + type: Identifier; + byref: boolean; + nullable: boolean; + body: Block | null; + attrGroups: AttrGroup[]; + } + /** + * Imports a variable from the global scope + */ + class Global extends Statement { + items: Variable[]; + } + /** + * Defines goto statement + */ + class Goto extends Statement { + label: string; + } + /** + * Halts the compiler execution + * @property after - String after the halt statement + */ + class Halt extends Statement { + /** + * String after the halt statement + */ + after: string; + } + /** + * Defines an identifier node + */ + class Identifier extends Node { + name: string; + } + /** + * Defines a if statement + */ + class If extends Statement { + test: Expression; + body: Block; + alternate: Block | If | null; + shortForm: boolean; + } + /** + * Defines system include call + */ + class Include extends Expression { + target: Node; + once: boolean; + require: boolean; + } + /** + * Defines inline html output (treated as echo output) + */ + class Inline extends Literal { + value: string; + } + /** + * An interface definition + */ + class Interface extends Declaration { + extends: Identifier[]; + body: Declaration[]; + attrGroups: AttrGroup[]; + } + /** + * A union of types + */ + class IntersectionType extends Declaration { + types: TypeReference[]; + } + /** + * Defines an isset call + */ + class Isset extends Expression {} + /** + * A label statement (referenced by goto) + */ + class Label extends Statement { + name: string; + } + /** + * Defines list assignment + */ + class List extends Expression { + shortForm: boolean; + items: Entry[]; + } + /** + * Defines an array structure + */ + class Literal extends Expression { + raw: string; + value: EncapsedPart[] | Node | string | number | boolean | null; + } + /** + * Defines the location of the node (with it's source contents as string) + */ + class Location { + source: string | null; + start: Position; + end: Position; + } + /** + * Lookup on an offset in the specified object + */ + class Lookup extends Expression { + what: Expression; + offset: Expression; + } + /** + * Defines magic constant + */ + class Magic extends Literal {} + /** + * Defines a match expression + * @property cond - Condition expression to match against + * @property arms - Arms for comparison + */ + class Match extends Expression { + /** + * Condition expression to match against + */ + cond: Expression; + /** + * Arms for comparison + */ + arms: MatchArm[]; + } + /** + * An array entry - see [Array](#array) + * @property conds - The match condition expression list - null indicates default arm + * @property body - The return value expression + */ + class MatchArm extends Expression { + /** + * The match condition expression list - null indicates default arm + */ + conds: Expression[] | null; + /** + * The return value expression + */ + body: Expression; + } + /** + * Defines a class/interface/trait method + */ + class Method extends Function { + isAbstract: boolean; + isFinal: boolean; + isStatic: boolean; + visibility: string; + } + /** + * Defines a class reference node + */ + class Name extends Reference { + /** + * This is an identifier without a namespace separator, such as Foo + */ + readonly UNQUALIFIED_NAME: string; + /** + * This is an identifier with a namespace separator, such as Foo\Bar + */ + readonly QUALIFIED_NAME: string; + /** + * This is an identifier with a namespace separator that begins with + * a namespace separator, such as \Foo\Bar. The namespace \Foo is also + * a fully qualified name. + */ + readonly FULL_QUALIFIED_NAME: string; + /** + * This is an identifier starting with namespace, such as namespace\Foo\Bar. + */ + readonly RELATIVE_NAME: string; + name: string; + resolution: string; + } + /** + * Named arguments. + */ + class namedargument extends Expression { + name: string; + value: Expression; + } + /** + * The main program node + */ + class Namespace extends Block { + name: string; + withBrackets: boolean; + } + /** + * Creates a new instance of the specified class + */ + class New extends Expression { + what: Identifier | Variable | Class; + arguments: Variable[]; + } + /** + * A generic AST node + */ + class Node { + /** + * Attach comments to current node + */ + setTrailingComments(docs: any): void; + /** + * Destroying an unused node + */ + destroy(): void; + /** + * Includes current token position of the parser + */ + includeToken(parser: any): void; + /** + * Helper for extending the Node class + */ + static extends( + type: string, + constructor: (...params: any[]) => any, + ): (...params: any[]) => any; + loc: Location | null; + leadingComments: CommentBlock[] | Comment[] | null; + trailingComments: CommentBlock[] | Comment[] | null; + kind: string; + } + /** + * Ignore this node, it implies a no operation block, for example : + * [$foo, $bar, /* here a noop node * /] + */ + class Noop extends Node {} + /** + * Defines a nowdoc string + */ + class NowDoc extends Literal { + label: string; + raw: string; + value: string; + } + /** + * Represents the null keyword + */ + class NullKeyword extends Node {} + /** + * Lookup to an object property + */ + class NullSafePropertyLookup extends Lookup {} + /** + * Defines a numeric value + */ + class Number extends Literal { + value: number; + } + /** + * Lookup on an offset in an array + */ + class OffsetLookup extends Lookup {} + /** + * Defines binary operations + */ + class Operation extends Expression {} + type MODIFIER_PUBLIC = 1; + type MODIFIER_PROTECTED = 2; + type MODIFIER_PRIVATE = 4; + /** + * Defines a function parameter + */ + class Parameter extends Declaration { + type: Identifier | null; + value: Node | null; + byref: boolean; + variadic: boolean; + readonly: boolean; + nullable: boolean; + attrGroups: AttrGroup[]; + flags: MODIFIER_PUBLIC | MODIFIER_PROTECTED | MODIFIER_PRIVATE; + } + /** + * Defines a class reference node + */ + class ParentReference extends Reference {} + /** + * Each Position object consists of a line number (1-indexed) and a column number (0-indexed): + */ + class Position { + line: number; + column: number; + offset: number; + } + /** + * Defines a post operation `$i++` or `$i--` + */ + class Post extends Operation { + type: string; + what: Variable; + } + /** + * Defines a pre operation `++$i` or `--$i` + */ + class Pre extends Operation { + type: string; + what: Variable; + } + /** + * Outputs + */ + class Print extends Expression {} + /** + * The main program node + */ + class Program extends Block { + errors: Error[]; + comments: Comment[] | null; + tokens: String[] | null; + } + /** + * Defines a class property + */ + class Property extends Statement { + name: string; + value: Node | null; + readonly: boolean; + nullable: boolean; + type: Identifier | Identifier[] | null; + attrGroups: AttrGroup[]; + } + /** + * Lookup to an object property + */ + class PropertyLookup extends Lookup {} + /** + * Declares a properties into the current scope + */ + class PropertyStatement extends Statement { + /** + * Generic flags parser + */ + parseFlags(flags: (number | null)[]): void; + properties: Property[]; + visibility: string | null; + isStatic: boolean; + } + /** + * Defines a reference node + */ + class Reference extends Node {} + /** + * Defines a short if statement that returns a value + */ + class RetIf extends Expression { + test: Expression; + trueExpr: Expression; + falseExpr: Expression; + } + /** + * A continue statement + */ + class Return extends Statement { + expr: Expression | null; + } + /** + * Defines a class reference node + */ + class SelfReference extends Reference {} + /** + * Avoids to show/log warnings & notices from the inner expression + */ + class Silent extends Expression { + expr: Expression; + } + /** + * Any statement. + */ + class Statement extends Node {} + /** + * Declares a static variable into the current scope + */ + class Static extends Statement { + variables: StaticVariable[]; + } + /** + * Lookup to a static property + */ + class StaticLookup extends Lookup {} + /** + * Defines a class reference node + */ + class StaticReference extends Reference {} + /** + * Defines a constant + */ + class StaticVariable extends Node { + variable: Variable; + defaultValue: Node | string | number | boolean | null; + } + /** + * Defines a string (simple or double quoted) - chars are already escaped + */ + class String extends Literal { + unicode: boolean; + isDoubleQuote: boolean; + value: string; + } + /** + * Defines a switch statement + */ + class Switch extends Statement { + test: Expression; + body: Block; + shortForm: boolean; + } + /** + * Defines a throw statement + */ + class Throw extends Statement { + what: Expression; + } + /** + * A trait definition + */ + class Trait extends Declaration { + body: Declaration[]; + } + /** + * Defines a trait alias + */ + class TraitAlias extends Node { + trait: Identifier | null; + method: Identifier; + as: Identifier | null; + visibility: string | null; + } + /** + * Defines a trait alias + */ + class TraitPrecedence extends Node { + trait: Identifier | null; + method: Identifier; + instead: Identifier[]; + } + /** + * Defines a trait usage + */ + class TraitUse extends Node { + traits: Identifier[]; + adaptations: Node[] | null; + } + /** + * Defines a try statement + */ + class Try extends Statement { + body: Block; + catches: Catch[]; + always: Block; + } + /** + * Defines a class reference node + */ + class TypeReference extends Reference { + name: string; + } + /** + * Unary operations + */ + class Unary extends Operation { + type: string; + what: Expression; + } + /** + * A union of types + */ + class UnionType extends Declaration { + types: TypeReference[]; + } + /** + * Deletes references to a list of variables + */ + class Unset extends Statement {} + /** + * Defines a use statement (with a list of use items) + * @property type - Possible value : function, const + */ + class UseGroup extends Statement { + name: string | null; + /** + * Possible value : function, const + */ + type: string | null; + item: UseItem[]; + } + /** + * Defines a use statement (from namespace) + * @property type - Possible value : function, const + */ + class UseItem extends Statement { + /** + * Importing a constant + */ + readonly TYPE_CONST: string; + /** + * Importing a function + */ + readonly TYPE_FUNC: string; + name: string; + /** + * Possible value : function, const + */ + type: string | null; + alias: Identifier | null; + } + /** + * Any expression node. Since the left-hand side of an assignment may + * be any expression in general, an expression can also be a pattern. + * @example + * // PHP code : + * $foo + * // AST output + * { + * "kind": "variable", + * "name": "foo", + * "curly": false + * } + * @property name - The variable name (can be a complex expression when the name is resolved dynamically) + * @property curly - Indicate if the name is defined between curlies, ex `${foo}` + */ + class Variable extends Expression { + /** + * The variable name (can be a complex expression when the name is resolved dynamically) + */ + name: string | Node; + /** + * Indicate if the name is defined between curlies, ex `${foo}` + */ + curly: boolean; + } + /** + * Introduce a list of items into the arguments of the call + */ + class Variadic extends Expression { + what: any[] | Expression; + } + /** + * Defines a variadic placeholder (the ellipsis in PHP 8.1+'s first-class callable syntax) + */ + class VariadicPlaceholder extends Node {} + /** + * Defines a while statement + */ + class While extends Statement { + test: Expression; + body: Block | null; + shortForm: boolean; + } + /** + * Defines a yield generator statement + */ + class Yield extends Expression { + value: Expression | null; + key: Expression | null; + } + /** + * Defines a yield from generator statement + */ + class YieldFrom extends Expression { + value: Expression; + } + /** + * The AST builder class + * @property withPositions - Should locate any node (by default false) + * @property withSource - Should extract the node original code (by default false) + */ + class AST { + /** + * Should locate any node (by default false) + */ + withPositions: boolean; + /** + * Should extract the node original code (by default false) + */ + withSource: boolean; + } + /** + * Initialise a new parser instance with the specified options + * @example + * var parser = require('php-parser'); + * var instance = new parser({ + * parser: { + * extractDoc: true, + * suppressErrors: true, + * version: 704 // or '7.4' + * }, + * ast: { + * withPositions: true + * }, + * lexer: { + * short_tags: true, + * asp_tags: true + * } + * }); + * + * var evalAST = instance.parseEval('some php code'); + * var codeAST = instance.parseCode(' Note that the output tokens are *STRICLY* similar to PHP function `token_get_all` + * @returns - Each item can be a string or an array with following informations [token_name, text, line_number] + */ + tokenGetAll(buffer: string): (string | string[])[]; + lexer: Lexer; + parser: Parser; + ast: AST; + tokens: any; + } + /** + * This is the php lexer. It will tokenize the string for helping the + * parser to build the AST from its grammar. + * @property all_tokens - defines if all tokens must be retrieved (used by token_get_all only) + * @property comment_tokens - extracts comments tokens + * @property mode_eval - enables the evald mode (ignore opening tags) + * @property asp_tags - disables by default asp tags mode + * @property short_tags - enables by default short tags mode + * @property keywords - List of php keyword + * @property castKeywords - List of php keywords for type casting + */ + class Lexer { + /** + * Initialize the lexer with the specified input + */ + setInput(): void; + /** + * consumes and returns one char from the input + */ + input(): void; + /** + * revert eating specified size + */ + unput(): void; + /** + * check if the text matches + */ + tryMatch(text: string): boolean; + /** + * check if the text matches + */ + tryMatchCaseless(text: string): boolean; + /** + * look ahead + */ + ahead(size: number): string; + /** + * consume the specified size + */ + consume(size: number): Lexer; + /** + * Gets the current state + */ + getState(): void; + /** + * Sets the current lexer state + */ + setState(): void; + /** + * prepend next token + */ + appendToken(value: any, ahead: any): Lexer; + /** + * return next match that has a token + */ + lex(): number | string; + /** + * activates a new lexer condition state (pushes the new lexer condition state onto the condition stack) + */ + begin(condition: any): Lexer; + /** + * pop the previously active lexer condition state off the condition stack + */ + popState(): string | any; + /** + * return next match in input + */ + next(): number | any; + EOF: number; + /** + * defines if all tokens must be retrieved (used by token_get_all only) + */ + all_tokens: boolean; + /** + * extracts comments tokens + */ + comment_tokens: boolean; + /** + * enables the evald mode (ignore opening tags) + */ + mode_eval: boolean; + /** + * disables by default asp tags mode + */ + asp_tags: boolean; + /** + * enables by default short tags mode + */ + short_tags: boolean; + /** + * List of php keyword + */ + keywords: any; + /** + * List of php keywords for type casting + */ + castKeywords: any; + } + /** + * The PHP Parser class that build the AST tree from the lexer + * @property lexer - current lexer instance + * @property ast - the AST factory instance + * @property token - current token + * @property extractDoc - should extract documentation as AST node + * @property extractTokens - should extract each token + * @property suppressErrors - should ignore parsing errors and continue + * @property debug - should output debug informations + */ + class Parser { + /** + * helper : gets a token name + */ + getTokenName(): void; + /** + * main entry point : converts a source code to AST + */ + parse(): void; + /** + * Raise an error + */ + raiseError(): void; + /** + * handling errors + */ + error(): void; + /** + * Create a position node from the lexers position + */ + position(): Position; + /** + * Creates a new AST node + */ + node(): void; + /** + * expects an end of statement or end of file + */ + expectEndOfStatement(): boolean; + /** + * Force the parser to check the current token. + * + * If the current token does not match to expected token, + * the an error will be raised. + * + * If the suppressError mode is activated, then the error will + * be added to the program error stack and this function will return `false`. + */ + expect(token: string | number): boolean; + /** + * Returns the current token contents + */ + text(): string; + /** + * consume the next token + */ + next(): void; + /** + * Peek at the next token. + * @returns Next Token + */ + peek(): string | number; + /** + * Eating a token + */ + lex(): void; + /** + * Check if token is of specified type + */ + is(): void; + /** + * current lexer instance + */ + lexer: Lexer; + /** + * the AST factory instance + */ + ast: AST; + /** + * current token + */ + token: number | string; + /** + * should extract documentation as AST node + */ + extractDoc: boolean; + /** + * should extract each token + */ + extractTokens: boolean; + /** + * should ignore parsing errors and continue + */ + suppressErrors: boolean; + /** + * should output debug informations + */ + debug: boolean; + } + const enum TokenNames { + T_HALT_COMPILER = 101, + T_USE = 102, + T_ENCAPSED_AND_WHITESPACE = 103, + T_OBJECT_OPERATOR = 104, + T_STRING = 105, + T_DOLLAR_OPEN_CURLY_BRACES = 106, + T_STRING_VARNAME = 107, + T_CURLY_OPEN = 108, + T_NUM_STRING = 109, + T_ISSET = 110, + T_EMPTY = 111, + T_INCLUDE = 112, + T_INCLUDE_ONCE = 113, + T_EVAL = 114, + T_REQUIRE = 115, + T_REQUIRE_ONCE = 116, + T_NAMESPACE = 117, + T_NS_SEPARATOR = 118, + T_AS = 119, + T_IF = 120, + T_ENDIF = 121, + T_WHILE = 122, + T_DO = 123, + T_FOR = 124, + T_SWITCH = 125, + T_BREAK = 126, + T_CONTINUE = 127, + T_RETURN = 128, + T_GLOBAL = 129, + T_STATIC = 130, + T_ECHO = 131, + T_INLINE_HTML = 132, + T_UNSET = 133, + T_FOREACH = 134, + T_DECLARE = 135, + T_TRY = 136, + T_THROW = 137, + T_GOTO = 138, + T_FINALLY = 139, + T_CATCH = 140, + T_ENDDECLARE = 141, + T_LIST = 142, + T_CLONE = 143, + T_PLUS_EQUAL = 144, + T_MINUS_EQUAL = 145, + T_MUL_EQUAL = 146, + T_DIV_EQUAL = 147, + T_CONCAT_EQUAL = 148, + T_MOD_EQUAL = 149, + T_AND_EQUAL = 150, + T_OR_EQUAL = 151, + T_XOR_EQUAL = 152, + T_SL_EQUAL = 153, + T_SR_EQUAL = 154, + T_INC = 155, + T_DEC = 156, + T_BOOLEAN_OR = 157, + T_BOOLEAN_AND = 158, + T_LOGICAL_OR = 159, + T_LOGICAL_AND = 160, + T_LOGICAL_XOR = 161, + T_SL = 162, + T_SR = 163, + T_IS_IDENTICAL = 164, + T_IS_NOT_IDENTICAL = 165, + T_IS_EQUAL = 166, + T_IS_NOT_EQUAL = 167, + T_IS_SMALLER_OR_EQUAL = 168, + T_IS_GREATER_OR_EQUAL = 169, + T_INSTANCEOF = 170, + T_INT_CAST = 171, + T_DOUBLE_CAST = 172, + T_STRING_CAST = 173, + T_ARRAY_CAST = 174, + T_OBJECT_CAST = 175, + T_BOOL_CAST = 176, + T_UNSET_CAST = 177, + T_EXIT = 178, + T_PRINT = 179, + T_YIELD = 180, + T_YIELD_FROM = 181, + T_FUNCTION = 182, + T_DOUBLE_ARROW = 183, + T_DOUBLE_COLON = 184, + T_ARRAY = 185, + T_CALLABLE = 186, + T_CLASS = 187, + T_ABSTRACT = 188, + T_TRAIT = 189, + T_FINAL = 190, + T_EXTENDS = 191, + T_INTERFACE = 192, + T_IMPLEMENTS = 193, + T_VAR = 194, + T_PUBLIC = 195, + T_PROTECTED = 196, + T_PRIVATE = 197, + T_CONST = 198, + T_NEW = 199, + T_INSTEADOF = 200, + T_ELSEIF = 201, + T_ELSE = 202, + T_ENDSWITCH = 203, + T_CASE = 204, + T_DEFAULT = 205, + T_ENDFOR = 206, + T_ENDFOREACH = 207, + T_ENDWHILE = 208, + T_CONSTANT_ENCAPSED_STRING = 209, + T_LNUMBER = 210, + T_DNUMBER = 211, + T_LINE = 212, + T_FILE = 213, + T_DIR = 214, + T_TRAIT_C = 215, + T_METHOD_C = 216, + T_FUNC_C = 217, + T_NS_C = 218, + T_START_HEREDOC = 219, + T_END_HEREDOC = 220, + T_CLASS_C = 221, + T_VARIABLE = 222, + T_OPEN_TAG = 223, + T_OPEN_TAG_WITH_ECHO = 224, + T_CLOSE_TAG = 225, + T_WHITESPACE = 226, + T_COMMENT = 227, + T_DOC_COMMENT = 228, + T_ELLIPSIS = 229, + T_COALESCE = 230, + T_POW = 231, + T_POW_EQUAL = 232, + T_SPACESHIP = 233, + T_COALESCE_EQUAL = 234, + T_FN = 235, + T_NULLSAFE_OBJECT_OPERATOR = 236, + T_MATCH = 237, + T_ATTRIBUTE = 238, + T_ENUM = 239, + T_READ_ONLY = 240, + T_NAME_RELATIVE = 241, + T_NAME_QUALIFIED = 242, + T_NAME_FULLY_QUALIFIED = 243, + } + /** + * PHP AST Tokens + */ + const tokens: { + values: { + [key: number]: string; + }; + names: TokenNames; + }; +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 000000000..40b783e10 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,61 @@ +const path = require("path"); +const webpack = require("webpack"); +const TerserPlugin = require("terser-webpack-plugin"); +const { name, description, license } = require("./package.json"); + +const entry = "./src/index.js"; + +const entries = { + [`${name}`]: entry, + [`${name}.min`]: entry, +}; + +const today = `${new Date(Date.now()).toLocaleDateString()}`; + +module.exports = { + target: "web", + mode: "production", + entry: entries, + output: { + filename: `[name].js`, + path: path.resolve(__dirname, "dist"), + library: "PhpParser", + libraryExport: "default", + libraryTarget: "umd", + }, + module: { + rules: [ + { + test: /\.js$/, + exclude: /(node_modules|bower_components)/, + use: { + loader: "babel-loader?cacheDirectory=true", + }, + }, + ], + }, + optimization: { + minimize: true, + minimizer: [ + new TerserPlugin({ + include: /\.min\.js$/, + terserOptions: { + mangle: true, + }, + }), + ], + }, + plugins: [ + new webpack.BannerPlugin({ + entryOnly: true, + banner: ` + Package: ${name} + ${description} + Build: [fullhash] - ${today} + Copyright (C) 2021 Glayzzle (${license}) + @authors https://github.com/glayzzle/php-parser/graphs/contributors + @url http://glayzzle.com + `, + }), + ], +}; diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..12e87ad70 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,5427 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.21.4": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39" + integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/code-frame@^7.12.13": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" + integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/compat-data@^7.22.0": + version "7.22.3" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.3.tgz#cd502a6a0b6e37d7ad72ce7e71a7160a3ae36f7e" + integrity sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ== + +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.9", "@babel/compat-data@^7.26.0": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.2.tgz#278b6b13664557de95b8f35b90d96785850bb56e" + integrity sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg== + +"@babel/core@^7.11.6", "@babel/core@^7.12.3": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.7.tgz#37072f951bd4d28315445f66e0ec9f6ae0c8c35f" + integrity sha512-t1ZjCluspe5DW24bn2Rr1CDb2v9rn/hROtg9a2tmd0+QYf4bsloYfLQzjG4qHPNMhWtKdGC33R5AxGR2Af2cBw== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.7" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.20.7" + "@babel/helpers" "^7.20.7" + "@babel/parser" "^7.20.7" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.1" + semver "^6.3.0" + +"@babel/core@^7.23.9", "@babel/core@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40" + integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.26.0" + "@babel/generator" "^7.26.0" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helpers" "^7.26.0" + "@babel/parser" "^7.26.0" + "@babel/template" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.26.0" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.20.7", "@babel/generator@^7.22.3": + version "7.22.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.3.tgz#0ff675d2edb93d7596c5f6728b52615cfc0df01e" + integrity sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A== + dependencies: + "@babel/types" "^7.22.3" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/generator@^7.25.9", "@babel/generator@^7.26.0": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.2.tgz#87b75813bec87916210e5e01939a4c823d6bb74f" + integrity sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw== + dependencies: + "@babel/parser" "^7.26.2" + "@babel/types" "^7.26.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + +"@babel/generator@^7.7.2": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a" + integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw== + dependencies: + "@babel/types" "^7.20.7" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-annotate-as-pure@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" + integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== + dependencies: + "@babel/types" "^7.25.9" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz#f41752fe772a578e67286e6779a68a5a92de1ee9" + integrity sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-compilation-targets@^7.20.7": + version "7.22.1" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.1.tgz#bfcd6b7321ffebe33290d68550e2c9d7eb7c7a58" + integrity sha512-Rqx13UM3yVB5q0D/KwQ8+SPfX/+Rnsy1Lw1k/UwOC4KC6qrzIQoY3lYnBu5EHKBlEHHcj0M0W8ltPSkD8rqfsQ== + dependencies: + "@babel/compat-data" "^7.22.0" + "@babel/helper-validator-option" "^7.21.0" + browserslist "^4.21.3" + lru-cache "^5.1.1" + semver "^6.3.0" + +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz#55af025ce365be3cdc0c1c1e56c6af617ce88875" + integrity sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ== + dependencies: + "@babel/compat-data" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-create-class-features-plugin@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz#7644147706bb90ff613297d49ed5266bde729f83" + integrity sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-member-expression-to-functions" "^7.25.9" + "@babel/helper-optimise-call-expression" "^7.25.9" + "@babel/helper-replace-supers" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/traverse" "^7.25.9" + semver "^6.3.1" + +"@babel/helper-create-regexp-features-plugin@^7.18.6": + version "7.22.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.1.tgz#a7ed9a8488b45b467fca353cd1a44dc5f0cf5c70" + integrity sha512-WWjdnfR3LPIe+0EY8td7WmjhytxXtjKAEpnAxun/hkNiyOaPlvGK+NZaBFIdi9ndYV3Gav7BpFvtUwnaJlwi1w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + regexpu-core "^5.3.1" + semver "^6.3.0" + +"@babel/helper-create-regexp-features-plugin@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz#3e8999db94728ad2b2458d7a470e7770b7764e26" + integrity sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + regexpu-core "^6.1.1" + semver "^6.3.1" + +"@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + +"@babel/helper-environment-visitor@^7.18.9", "@babel/helper-environment-visitor@^7.22.1": + version "7.22.1" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz#ac3a56dbada59ed969d712cf527bd8271fe3eba8" + integrity sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA== + +"@babel/helper-function-name@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" + integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== + dependencies: + "@babel/template" "^7.20.7" + "@babel/types" "^7.21.0" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-member-expression-to-functions@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3" + integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-module-imports@^7.18.6": + version "7.21.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz#ac88b2f76093637489e718a90cec6cf8a9b029af" + integrity sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg== + dependencies: + "@babel/types" "^7.21.4" + +"@babel/helper-module-imports@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" + integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-module-transforms@^7.20.7": + version "7.20.11" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" + integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.10" + "@babel/types" "^7.20.7" + +"@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" + integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/helper-optimise-call-expression@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" + integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ== + dependencies: + "@babel/types" "^7.25.9" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz#345f2377d05a720a4e5ecfa39cbf4474a4daed56" + integrity sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg== + +"@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz#9cbdd63a9443a2c92a725cca7ebca12cc8dd9f46" + integrity sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw== + +"@babel/helper-remap-async-to-generator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" + integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-wrap-function" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/helper-replace-supers@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz#ba447224798c3da3f8713fc272b145e33da6a5c5" + integrity sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.25.9" + "@babel/helper-optimise-call-expression" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/helper-simple-access@^7.20.2": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz#d697a7971a5c39eac32c7e63c0921c06c8a249ee" + integrity sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg== + dependencies: + "@babel/types" "^7.21.5" + +"@babel/helper-simple-access@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz#6d51783299884a2c74618d6ef0f86820ec2e7739" + integrity sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-skip-transparent-expression-wrappers@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9" + integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.19.4", "@babel/helper-string-parser@^7.21.5": + version "7.21.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz#2b3eea65443c6bdc31c22d037c65f6d323b6b2bd" + integrity sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w== + +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + +"@babel/helper-validator-option@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180" + integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ== + +"@babel/helper-validator-option@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" + integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== + +"@babel/helper-wrap-function@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" + integrity sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g== + dependencies: + "@babel/template" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helpers@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.7.tgz#04502ff0feecc9f20ecfaad120a18f011a8e6dce" + integrity sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA== + dependencies: + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" + +"@babel/helpers@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.0.tgz#30e621f1eba5aa45fe6f4868d2e9154d884119a4" + integrity sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw== + dependencies: + "@babel/template" "^7.25.9" + "@babel/types" "^7.26.0" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.9.4": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.7.tgz#66fe23b3c8569220817d5feb8b9dcdc95bb4f71b" + integrity sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg== + +"@babel/parser@^7.20.7", "@babel/parser@^7.21.9", "@babel/parser@^7.22.4": + version "7.22.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.4.tgz#a770e98fd785c231af9d93f6459d36770993fb32" + integrity sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA== + +"@babel/parser@^7.23.9", "@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.2": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.2.tgz#fd7b6f487cfea09889557ef5d4eeb9ff9a5abd11" + integrity sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ== + dependencies: + "@babel/types" "^7.26.0" + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz#cc2e53ebf0a0340777fff5ed521943e253b4d8fe" + integrity sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz#af9e4fb63ccb8abcb92375b2fcfe36b60c774d30" + integrity sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz#e8dc26fcd616e6c5bf2bd0d5a2c151d4f92a9137" + integrity sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz#807a667f9158acac6f6164b4beb85ad9ebc9e1d1" + integrity sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/plugin-transform-optional-chaining" "^7.25.9" + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz#de7093f1e7deaf68eadd7cc6b07f2ab82543269e" + integrity sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-assertions@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz#620412405058efa56e4a564903b79355020f445f" + integrity sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-syntax-import-attributes@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz#3b1412847699eea739b4f2602c74ce36f6b0b0f7" + integrity sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845" + integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-async-generator-functions@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz#1b18530b077d18a407c494eb3d1d72da505283a2" + integrity sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-remap-async-to-generator" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/plugin-transform-async-to-generator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz#c80008dacae51482793e5a9c08b39a5be7e12d71" + integrity sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-remap-async-to-generator" "^7.25.9" + +"@babel/plugin-transform-block-scoped-functions@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz#5700691dbd7abb93de300ca7be94203764fce458" + integrity sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-block-scoping@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz#c33665e46b06759c93687ca0f84395b80c0473a1" + integrity sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-class-properties@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz#a8ce84fedb9ad512549984101fa84080a9f5f51f" + integrity sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-class-static-block@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz#6c8da219f4eb15cae9834ec4348ff8e9e09664a0" + integrity sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-classes@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52" + integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-replace-supers" "^7.25.9" + "@babel/traverse" "^7.25.9" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b" + integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/template" "^7.25.9" + +"@babel/plugin-transform-destructuring@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1" + integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-dotall-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz#bad7945dd07734ca52fe3ad4e872b40ed09bb09a" + integrity sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-duplicate-keys@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz#8850ddf57dce2aebb4394bb434a7598031059e6d" + integrity sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz#6f7259b4de127721a08f1e5165b852fcaa696d31" + integrity sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-dynamic-import@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz#23e917de63ed23c6600c5dd06d94669dce79f7b8" + integrity sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-exponentiation-operator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz#ece47b70d236c1d99c263a1e22b62dc20a4c8b0f" + integrity sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-export-namespace-from@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz#90745fe55053394f554e40584cda81f2c8a402a2" + integrity sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-for-of@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz#4bdc7d42a213397905d89f02350c5267866d5755" + integrity sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + +"@babel/plugin-transform-function-name@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97" + integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA== + dependencies: + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/plugin-transform-json-strings@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz#c86db407cb827cded902a90c707d2781aaa89660" + integrity sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de" + integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-logical-assignment-operators@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz#b19441a8c39a2fda0902900b306ea05ae1055db7" + integrity sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-member-expression-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz#63dff19763ea64a31f5e6c20957e6a25e41ed5de" + integrity sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-modules-amd@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz#49ba478f2295101544abd794486cd3088dddb6c5" + integrity sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw== + dependencies: + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-modules-commonjs@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz#d165c8c569a080baf5467bda88df6425fc060686" + integrity sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg== + dependencies: + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-simple-access" "^7.25.9" + +"@babel/plugin-transform-modules-systemjs@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz#8bd1b43836269e3d33307151a114bcf3ba6793f8" + integrity sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA== + dependencies: + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/plugin-transform-modules-umd@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz#6710079cdd7c694db36529a1e8411e49fcbf14c9" + integrity sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw== + dependencies: + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a" + integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-new-target@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz#42e61711294b105c248336dcb04b77054ea8becd" + integrity sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz#bcb1b0d9e948168102d5f7104375ca21c3266949" + integrity sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-numeric-separator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz#bfed75866261a8b643468b0ccfd275f2033214a1" + integrity sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-object-rest-spread@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz#0203725025074164808bcf1a2cfa90c652c99f18" + integrity sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg== + dependencies: + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/plugin-transform-parameters" "^7.25.9" + +"@babel/plugin-transform-object-super@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz#385d5de135162933beb4a3d227a2b7e52bb4cf03" + integrity sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-replace-supers" "^7.25.9" + +"@babel/plugin-transform-optional-catch-binding@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz#10e70d96d52bb1f10c5caaac59ac545ea2ba7ff3" + integrity sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-optional-chaining@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz#e142eb899d26ef715435f201ab6e139541eee7dd" + integrity sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + +"@babel/plugin-transform-parameters@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257" + integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-private-methods@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" + integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-private-property-in-object@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" + integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-property-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz#d72d588bd88b0dec8b62e36f6fda91cedfe28e3f" + integrity sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-regenerator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz#03a8a4670d6cebae95305ac6defac81ece77740b" + integrity sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-regexp-modifiers@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz#2f5837a5b5cd3842a919d8147e9903cc7455b850" + integrity sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-reserved-words@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz#0398aed2f1f10ba3f78a93db219b27ef417fb9ce" + integrity sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-shorthand-properties@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2" + integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-spread@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9" + integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + +"@babel/plugin-transform-sticky-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32" + integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-template-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz#6dbd4a24e8fad024df76d1fac6a03cf413f60fe1" + integrity sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-typeof-symbol@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz#224ba48a92869ddbf81f9b4a5f1204bbf5a2bc4b" + integrity sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-unicode-escapes@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz#a75ef3947ce15363fccaa38e2dd9bc70b2788b82" + integrity sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-unicode-property-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz#a901e96f2c1d071b0d1bb5dc0d3c880ce8f53dd3" + integrity sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-unicode-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1" + integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-unicode-sets-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz#65114c17b4ffc20fa5b163c63c70c0d25621fabe" + integrity sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/preset-env@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.26.0.tgz#30e5c6bc1bcc54865bff0c5a30f6d4ccdc7fa8b1" + integrity sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw== + dependencies: + "@babel/compat-data" "^7.26.0" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.25.9" + "@babel/plugin-bugfix-safari-class-field-initializer-scope" "^7.25.9" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.25.9" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.25.9" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.25.9" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-import-assertions" "^7.26.0" + "@babel/plugin-syntax-import-attributes" "^7.26.0" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.25.9" + "@babel/plugin-transform-async-generator-functions" "^7.25.9" + "@babel/plugin-transform-async-to-generator" "^7.25.9" + "@babel/plugin-transform-block-scoped-functions" "^7.25.9" + "@babel/plugin-transform-block-scoping" "^7.25.9" + "@babel/plugin-transform-class-properties" "^7.25.9" + "@babel/plugin-transform-class-static-block" "^7.26.0" + "@babel/plugin-transform-classes" "^7.25.9" + "@babel/plugin-transform-computed-properties" "^7.25.9" + "@babel/plugin-transform-destructuring" "^7.25.9" + "@babel/plugin-transform-dotall-regex" "^7.25.9" + "@babel/plugin-transform-duplicate-keys" "^7.25.9" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.25.9" + "@babel/plugin-transform-dynamic-import" "^7.25.9" + "@babel/plugin-transform-exponentiation-operator" "^7.25.9" + "@babel/plugin-transform-export-namespace-from" "^7.25.9" + "@babel/plugin-transform-for-of" "^7.25.9" + "@babel/plugin-transform-function-name" "^7.25.9" + "@babel/plugin-transform-json-strings" "^7.25.9" + "@babel/plugin-transform-literals" "^7.25.9" + "@babel/plugin-transform-logical-assignment-operators" "^7.25.9" + "@babel/plugin-transform-member-expression-literals" "^7.25.9" + "@babel/plugin-transform-modules-amd" "^7.25.9" + "@babel/plugin-transform-modules-commonjs" "^7.25.9" + "@babel/plugin-transform-modules-systemjs" "^7.25.9" + "@babel/plugin-transform-modules-umd" "^7.25.9" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.25.9" + "@babel/plugin-transform-new-target" "^7.25.9" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.25.9" + "@babel/plugin-transform-numeric-separator" "^7.25.9" + "@babel/plugin-transform-object-rest-spread" "^7.25.9" + "@babel/plugin-transform-object-super" "^7.25.9" + "@babel/plugin-transform-optional-catch-binding" "^7.25.9" + "@babel/plugin-transform-optional-chaining" "^7.25.9" + "@babel/plugin-transform-parameters" "^7.25.9" + "@babel/plugin-transform-private-methods" "^7.25.9" + "@babel/plugin-transform-private-property-in-object" "^7.25.9" + "@babel/plugin-transform-property-literals" "^7.25.9" + "@babel/plugin-transform-regenerator" "^7.25.9" + "@babel/plugin-transform-regexp-modifiers" "^7.26.0" + "@babel/plugin-transform-reserved-words" "^7.25.9" + "@babel/plugin-transform-shorthand-properties" "^7.25.9" + "@babel/plugin-transform-spread" "^7.25.9" + "@babel/plugin-transform-sticky-regex" "^7.25.9" + "@babel/plugin-transform-template-literals" "^7.25.9" + "@babel/plugin-transform-typeof-symbol" "^7.25.9" + "@babel/plugin-transform-unicode-escapes" "^7.25.9" + "@babel/plugin-transform-unicode-property-regex" "^7.25.9" + "@babel/plugin-transform-unicode-regex" "^7.25.9" + "@babel/plugin-transform-unicode-sets-regex" "^7.25.9" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.6" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.38.1" + semver "^6.3.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + +"@babel/runtime@^7.8.4": + version "7.22.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.3.tgz#0a7fce51d43adbf0f7b517a71f4c3aaca92ebcbb" + integrity sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ== + dependencies: + regenerator-runtime "^0.13.11" + +"@babel/template@^7.20.7": + version "7.21.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.21.9.tgz#bf8dad2859130ae46088a99c1f265394877446fb" + integrity sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ== + dependencies: + "@babel/code-frame" "^7.21.4" + "@babel/parser" "^7.21.9" + "@babel/types" "^7.21.5" + +"@babel/template@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016" + integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg== + dependencies: + "@babel/code-frame" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/template@^7.3.3": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + +"@babel/traverse@^7.20.10", "@babel/traverse@^7.20.7": + version "7.22.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.4.tgz#c3cf96c5c290bd13b55e29d025274057727664c0" + integrity sha512-Tn1pDsjIcI+JcLKq1AVlZEr4226gpuAQTsLMorsYg9tuS/kG7nuwwJ4AB8jfQuEgb/COBwR/DqJxmoiYFu5/rQ== + dependencies: + "@babel/code-frame" "^7.21.4" + "@babel/generator" "^7.22.3" + "@babel/helper-environment-visitor" "^7.22.1" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.22.4" + "@babel/types" "^7.22.4" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.9.tgz#a50f8fe49e7f69f53de5bea7e413cd35c5e13c84" + integrity sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw== + dependencies: + "@babel/code-frame" "^7.25.9" + "@babel/generator" "^7.25.9" + "@babel/parser" "^7.25.9" + "@babel/template" "^7.25.9" + "@babel/types" "^7.25.9" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" + integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== + dependencies: + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + +"@babel/types@^7.18.6", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.4", "@babel/types@^7.21.5", "@babel/types@^7.22.3", "@babel/types@^7.22.4", "@babel/types@^7.4.4": + version "7.22.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.4.tgz#56a2653ae7e7591365dabf20b76295410684c071" + integrity sha512-Tx9x3UBHTTsMSW85WB2kphxYQVvrZ/t1FxD88IpSgIjiUJlCm9z+xWIDwyo1vffTwSqteqyznB8ZE9vYYk16zA== + dependencies: + "@babel/helper-string-parser" "^7.21.5" + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + +"@babel/types@^7.25.9", "@babel/types@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.0.tgz#deabd08d6b753bc8e0f198f8709fb575e31774ff" + integrity sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/eslint-utils@^4.4.0": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" + integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.12.1": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + +"@eslint/config-array@^0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.18.0.tgz#37d8fe656e0d5e3dbaea7758ea56540867fd074d" + integrity sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw== + dependencies: + "@eslint/object-schema" "^2.1.4" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/core@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.7.0.tgz#a1bb4b6a4e742a5ff1894b7ee76fbf884ec72bd3" + integrity sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw== + +"@eslint/eslintrc@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6" + integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.14.0", "@eslint/js@^9.14.0": + version "9.14.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.14.0.tgz#2347a871042ebd11a00fd8c2d3d56a265ee6857e" + integrity sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg== + +"@eslint/object-schema@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.4.tgz#9e69f8bb4031e11df79e03db09f9dbbae1740843" + integrity sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ== + +"@eslint/plugin-kit@^0.2.0": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz#5eff371953bc13e3f4d88150e2c53959f64f74f6" + integrity sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw== + dependencies: + levn "^0.4.1" + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.6" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" + integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.3.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== + +"@humanwhocodes/retry@^0.4.0": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" + integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/source-map@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.3.tgz#8108265659d4c33e72ffe14e33d6cc5eb59f2fda" + integrity sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.12": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@pkgr/core@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" + integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3" + integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz#d10549ed1f423d80639c528b6c7f5a1017747d0c" + integrity sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw== + dependencies: + "@sinonjs/commons" "^2.0.0" + +"@types/babel__core@^7.1.14": + version "7.1.20" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.20.tgz#e168cdd612c92a2d335029ed62ac94c95b362359" + integrity sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.4" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.1" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" + integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.18.3" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.3.tgz#dfc508a85781e5698d5b33443416b6268c4b3e8d" + integrity sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w== + dependencies: + "@babel/types" "^7.3.0" + +"@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + +"@types/graceful-fs@^4.1.3": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/json-schema@^7.0.8": + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== + +"@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/linkify-it@*": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.2.tgz#fd2cd2edbaa7eaac7e7f3c1748b52a19143846c9" + integrity sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA== + +"@types/markdown-it@^12.2.3": + version "12.2.3" + resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-12.2.3.tgz#0d6f6e5e413f8daaa26522904597be3d6cd93b51" + integrity sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ== + dependencies: + "@types/linkify-it" "*" + "@types/mdurl" "*" + +"@types/mdurl@*": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" + integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== + +"@types/node@*": + version "20.2.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb" + integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ== + +"@types/node@^22.9.0": + version "22.9.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.0.tgz#b7f16e5c3384788542c72dc3d561a7ceae2c0365" + integrity sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ== + dependencies: + undici-types "~6.19.8" + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^17.0.8": + version "17.0.18" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.18.tgz#466225ab4fbabb9aa711f5b406796daf1374a5b7" + integrity sha512-eIJR1UER6ur3EpKM3d+2Pgd+ET+k6Kn9B4ZItX0oPjjVI5PrfaRjKyLT5UYendDpLuoiJMNJvovLQbEXqhsPaw== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/scope-manager@8.13.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz#2f4aed0b87d72360e64e4ea194b1fde14a59082e" + integrity sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA== + dependencies: + "@typescript-eslint/types" "8.13.0" + "@typescript-eslint/visitor-keys" "8.13.0" + +"@typescript-eslint/types@8.13.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.13.0.tgz#3f35dead2b2491a04339370dcbcd17bbdfc204d8" + integrity sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng== + +"@typescript-eslint/typescript-estree@8.13.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz#db8c93dd5437ca3ce417a255fb35ddc3c12c3e95" + integrity sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g== + dependencies: + "@typescript-eslint/types" "8.13.0" + "@typescript-eslint/visitor-keys" "8.13.0" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/utils@^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.13.0.tgz#f6d40e8b5053dcaeabbd2e26463857abf27d62c0" + integrity sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.13.0" + "@typescript-eslint/types" "8.13.0" + "@typescript-eslint/typescript-estree" "8.13.0" + +"@typescript-eslint/visitor-keys@8.13.0": + version "8.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz#e97b0d92b266ef38a1faf40a74da289b66683a5b" + integrity sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw== + dependencies: + "@typescript-eslint/types" "8.13.0" + eslint-visitor-keys "^3.4.3" + +"@webassemblyjs/ast@1.13.1", "@webassemblyjs/ast@^1.12.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.13.1.tgz#4bf991409845051ce9fd3d36ebcd49bb75faae4c" + integrity sha512-+Zp/YJMBws+tg2Nuy5jiFhwvPiSeIB0gPp1Ie/TyqFg69qJ/vRrOKQ7AsFLn3solq5/9ubkBjrGd0UcvFjFsYA== + dependencies: + "@webassemblyjs/helper-numbers" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.12.1" + +"@webassemblyjs/floating-point-hex-parser@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.12.1.tgz#e92ce6f1d663d5a44127b751ee6cee335b8e3e20" + integrity sha512-0vqwjuCO3Sa6pO3nfplawORkL1GUgza/H1A62SdXHSFCmAHoRcrtX/yVG3f1LuMYW951cvYRcRt6hThhz4FnCQ== + +"@webassemblyjs/helper-api-error@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.12.1.tgz#e310b66234838b0c77d38741346b2b575dc4c047" + integrity sha512-czovmKZdRk4rYauCOuMV/EImC3qyfcqyJuOYyDRYR6PZSOW37VWe26fAZQznbvKjlwJdyxLl6mIfx47Cfz8ykw== + +"@webassemblyjs/helper-buffer@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.13.1.tgz#65f9d5d0d42ff9c2bdf9768d9368fd2fdab36185" + integrity sha512-J0gf97+D3CavG7aO5XmtwxRWMiMEuxQ6t8Aov8areSnyI5P5fM0HV0m8bE3iLfDQZBhxLCc15tRsFVOGyAJ0ng== + +"@webassemblyjs/helper-numbers@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.12.1.tgz#3b7239d8c5b4bab237b9138b231f3a0837a3ca27" + integrity sha512-Vp6k5nXOMvI9dWJqDGCMvwAc8+G6tI2YziuYWqxk7XYnWHdxEJo19CGpqm/kRh86rJxwYANLGuyreARhM+C9lQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.12.1" + "@webassemblyjs/helper-api-error" "1.12.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.12.1.tgz#2008ce69b4129a6e66c435498557eaa7957b3eae" + integrity sha512-flsRYmCqN2ZJmvAyNxZXPPFkwKoezeTUczytfBovql8cOjYTr6OTcZvku4UzyKFW0Kj+PgD+UaG8/IdX31EYWg== + +"@webassemblyjs/helper-wasm-section@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.13.1.tgz#3f7b438d4226f12fba60bf8e11e871343756f072" + integrity sha512-lcVNbrM5Wm7867lmbU61l+R4dU7emD2X70f9V0PuicvsdVUS5vvXODAxRYGVGBAJ6rWmXMuZKjM0PoeBjAcm2A== + dependencies: + "@webassemblyjs/ast" "1.13.1" + "@webassemblyjs/helper-buffer" "1.13.1" + "@webassemblyjs/helper-wasm-bytecode" "1.12.1" + "@webassemblyjs/wasm-gen" "1.13.1" + +"@webassemblyjs/ieee754@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.12.1.tgz#6c27377183eb6b0b9f6dacbd37bc143ba56e97ff" + integrity sha512-fcrUCqE2dVldeVAHTWFiTiKMS9ivc5jOgB2c30zYOZnm3O54SWeMJWS/HXYK862we2AYHtf6GYuP9xG9J+5zyQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.12.1.tgz#cc30f0ea19e5f8efdf8b247c2bc5627d64dcb621" + integrity sha512-jOU6pTFNf7aGm46NCrEU7Gj6cVuP55T7+kyo5TU/rCduZ5EdwMPBZwSwwzjPZ3eFXYFCmC5wZdPZN0ZWio6n4Q== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.12.1.tgz#f7f9eaaf1fd0835007672b628907cf5ccf916ee7" + integrity sha512-zcZvnAY3/M28Of012dksIfC26qZQJlj2PQCCvxqlsRJHOYtasp+OvK8nRcg11TKzAAv3ja7Y0NEBMKAjH6ljnw== + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.13.1.tgz#84a7c07469bf03589c82afd23c0b26b75a3443c9" + integrity sha512-YHnh/f4P4ggjPB+pcri8Pb2HHwCGK+B8qBE+NeEp/WTMQ7dAjgWTnLhXxUqb6WLOT25TK5m0VTCAKTYw8AKxcg== + dependencies: + "@webassemblyjs/ast" "1.13.1" + "@webassemblyjs/helper-buffer" "1.13.1" + "@webassemblyjs/helper-wasm-bytecode" "1.12.1" + "@webassemblyjs/helper-wasm-section" "1.13.1" + "@webassemblyjs/wasm-gen" "1.13.1" + "@webassemblyjs/wasm-opt" "1.13.1" + "@webassemblyjs/wasm-parser" "1.13.1" + "@webassemblyjs/wast-printer" "1.13.1" + +"@webassemblyjs/wasm-gen@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.13.1.tgz#a821f9a139b72da9614238ecddd3d7ae2a366f64" + integrity sha512-AxWiaqIeLh3c1H+8d1gPgVNXHyKP7jDu2G828Of9/E0/ovVEsh6LjX1QZ6g1tFBHocCwuUHK9O4w35kgojZRqA== + dependencies: + "@webassemblyjs/ast" "1.13.1" + "@webassemblyjs/helper-wasm-bytecode" "1.12.1" + "@webassemblyjs/ieee754" "1.12.1" + "@webassemblyjs/leb128" "1.12.1" + "@webassemblyjs/utf8" "1.12.1" + +"@webassemblyjs/wasm-opt@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.13.1.tgz#eaa4e9946c46427fb025e837dbfc235a400c7581" + integrity sha512-SUMlvCrfykC7dtWX5g4TSuMmWi9w9tK5kGIdvQMnLuvJfnFLsnAaF86FNbSBSAL33VhM/hOhx4t9o66N37IqSg== + dependencies: + "@webassemblyjs/ast" "1.13.1" + "@webassemblyjs/helper-buffer" "1.13.1" + "@webassemblyjs/wasm-gen" "1.13.1" + "@webassemblyjs/wasm-parser" "1.13.1" + +"@webassemblyjs/wasm-parser@1.13.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.13.1.tgz#42c20ec9a340865c3ba4fea8a19566afda90283e" + integrity sha512-8SPOcbqSb7vXHG+B0PTsJrvT/HilwV3WkJgxw34lmhWvO+7qM9xBTd9u4dn1Lb86WHpKswT5XwF277uBTHFikg== + dependencies: + "@webassemblyjs/ast" "1.13.1" + "@webassemblyjs/helper-api-error" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.12.1" + "@webassemblyjs/ieee754" "1.12.1" + "@webassemblyjs/leb128" "1.12.1" + "@webassemblyjs/utf8" "1.12.1" + +"@webassemblyjs/wast-printer@1.13.1": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.13.1.tgz#a82ff5e16eb6411fe10a8a06925bfa1b35230d74" + integrity sha512-q0zIfwpbFvaNkgbSzkZFzLsOs8ixZ5MSdTTMESilSAk1C3P8BKEWfbLEvIqyI/PjNpP9+ZU+/KwgfXx3T7ApKw== + dependencies: + "@webassemblyjs/ast" "1.13.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== + +"@webpack-cli/info@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== + +"@webpack-cli/serve@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.14.0: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== + +acorn@^8.8.2: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.0, ajv@^8.8.0: + version "8.11.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.2.tgz#aecb20b50607acf2569b6382167b65a96008bb78" + integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + integrity sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw== + dependencies: + ansi-wrap "0.1.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +ansi-wrap@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw== + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-differ@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + integrity sha512-LeZY+DZDRnvP7eMuQ6LHfCzUGxAAIViUBliK24P3hWXL6y4SortgR6Nim6xrkfSLlmH0+k+9NYNwVC2s53ZrYQ== + +array-uniq@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + +async@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-loader@^9.2.1: + version "9.2.1" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.2.1.tgz#04c7835db16c246dd19ba0914418f3937797587b" + integrity sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA== + dependencies: + find-cache-dir "^4.0.0" + schema-utils "^4.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.11" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.2" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.10.6: + version "0.10.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" + integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + core-js-compat "^3.38.0" + +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + +beeper@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" + integrity sha512-3vqtKL1N45I5dV0RdssXZG7X6pCqQrWPNOlBPZPrd+QkE2HEhR57Z04m0KtpbsZH73j+a3F8UD1TQnn+ExTvIA== + +benchmark@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629" + integrity sha512-l9MlfN4M1K/H2fbhfMy3B7vJd6AGKJVQn2h6Sg/Yx+KckoUA7ewS5Vv6TjSq18ooE1kS9hhAlQRH3AkXIh/aOQ== + dependencies: + lodash "^4.17.4" + platform "^1.3.3" + +bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.21.3: + version "4.21.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.7.tgz#e2b420947e5fb0a58e8f4668ae6e23488127e551" + integrity sha512-BauCXrQ7I2ftSqd2mvKHGo85XR0u7Ru3C/Hxsy/0TkfCtjrmAbPdzLGasmoiBxplpDXlPvdjX9u7srIMfgasNA== + dependencies: + caniuse-lite "^1.0.30001489" + electron-to-chromium "^1.4.411" + node-releases "^2.0.12" + update-browserslist-db "^1.0.11" + +browserslist@^4.24.0, browserslist@^4.24.2: + version "4.24.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.2.tgz#f5845bc91069dbd55ee89faf9822e1d885d16580" + integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg== + dependencies: + caniuse-lite "^1.0.30001669" + electron-to-chromium "^1.5.41" + node-releases "^2.0.18" + update-browserslist-db "^1.1.1" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffers@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" + integrity sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ== + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001489: + version "1.0.30001495" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001495.tgz#64a0ccef1911a9dcff647115b4430f8eff1ef2d9" + integrity sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg== + +caniuse-lite@^1.0.30001669: + version "1.0.30001677" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz#27c2e2c637e007cfa864a16f7dfe7cde66b38b5f" + integrity sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +catharsis@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/catharsis/-/catharsis-0.9.0.tgz#40382a168be0e6da308c277d3a2b3eb40c7d2121" + integrity sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A== + dependencies: + lodash "^4.17.15" + +chalk@^1.0.0, chalk@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +ci-info@^3.2.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.0.tgz#6d01b3696c59915b6ce057e4aa4adfc2fa25f5ef" + integrity sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog== + +cjs-module-lexer@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" + integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clone-stats@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" + integrity sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA== + +clone@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +colorette@^2.0.14: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +common-path-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" + integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +core-js-compat@^3.38.0, core-js-compat@^3.38.1: + version "3.39.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.39.0.tgz#b12dccb495f2601dc860bdbe7b4e3ffa8ba63f61" + integrity sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw== + dependencies: + browserslist "^4.24.2" + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cosmiconfig@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + +coveralls@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.1.tgz#f5d4431d8b5ae69c5079c8f8ca00d64ac77cf081" + integrity sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww== + dependencies: + js-yaml "^3.13.1" + lcov-parse "^1.0.0" + log-driver "^1.2.7" + minimist "^1.2.5" + request "^2.88.2" + +create-jest-runner@^0.11.2: + version "0.11.2" + resolved "https://registry.yarnpkg.com/create-jest-runner/-/create-jest-runner-0.11.2.tgz#4b4f62ccef1e4de12e80f81c2cf8211fa392a962" + integrity sha512-6lwspphs4M1PLKV9baBNxHQtWVBPZuDU8kAP4MyrVWa6aEpEcpi2HZeeA6WncwaqgsGNXpP0N2STS7XNM/nHKQ== + dependencies: + chalk "^4.1.0" + jest-worker "^28.0.2" + throat "^6.0.1" + +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + +dateformat@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" + integrity sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw== + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +debug@^4.3.1: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +dedent@^1.0.0: + version "1.5.3" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" + integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +dot-prop@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083" + integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== + dependencies: + is-obj "^2.0.0" + +duplexer2@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + integrity sha512-+AWBwjGadtksxjOQSFDhPNQbed7icNXApT4+2BNpsXzcCBiInq2H9XW0O8sfHFaPmnQRs7cg/P0fAr2IWQSW0g== + dependencies: + readable-stream "~1.1.9" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +electron-to-chromium@^1.4.411: + version "1.4.423" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.423.tgz#99567f3a0563fe0d1d0931e9ce851bca239f6658" + integrity sha512-y4A7YfQcDGPAeSWM1IuoWzXpg9RY1nwHzHSwRtCSQFp9FgAVDgdWlFf0RbdWfLWQ2WUI+bddUgk5RgTjqRE6FQ== + +electron-to-chromium@^1.5.41: + version "1.5.52" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.52.tgz#2bed832c95a56a195504f918150e548474687da8" + integrity sha512-xtoijJTZ+qeucLBDNztDOuQBE1ksqjvNjvqFoST3nGC7fSpqJ+X6BdTBaY5BHG+IhWWmpc6b/KfpeuEDupEPOQ== + +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +enhanced-resolve@^5.17.1: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +entities@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-module-lexer@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.2.1.tgz#ba303831f63e6a394983fde2f97ad77b22324527" + integrity sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-prettier@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" + integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== + +eslint-plugin-jest@^28.9.0: + version "28.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.9.0.tgz#19168dfaed124339cd2252c4c4d1ac3688aeb243" + integrity sha512-rLu1s1Wf96TgUUxSw6loVIkNtUjq1Re7A9QdCCHSohnvXEBAjuL420h0T/fMmkQlNsQP2GhQzEUpYHPfxBkvYQ== + dependencies: + "@typescript-eslint/utils" "^6.0.0 || ^7.0.0 || ^8.0.0" + +eslint-plugin-prettier@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz#d1c8f972d8f60e414c25465c163d16f209411f95" + integrity sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.9.1" + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" + integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" + integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== + +eslint@^9.14.0: + version "9.14.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.14.0.tgz#534180a97c00af08bcf2b60b0ebf0c4d6c1b2c95" + integrity sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.18.0" + "@eslint/core" "^0.7.0" + "@eslint/eslintrc" "^3.1.0" + "@eslint/js" "9.14.0" + "@eslint/plugin-kit" "^0.2.0" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.0" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.2.0" + eslint-visitor-keys "^4.2.0" + espree "^10.3.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + json-stable-stringify-without-jsonify "^1.0.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + text-table "^0.2.0" + +espree@^10.0.1, espree@^10.3.0: + version "10.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" + integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== + dependencies: + acorn "^8.14.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fancy-log@^1.1.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" + integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== + dependencies: + ansi-gray "^0.1.1" + color-support "^1.1.3" + parse-node-version "^1.0.0" + time-stamp "^1.0.0" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-cache-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-4.0.0.tgz#a30ee0448f81a3990708f6453633c733e2f6eec2" + integrity sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg== + dependencies: + common-path-prefix "^3.0.0" + pkg-dir "^7.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" + integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== + dependencies: + locate-path "^7.1.0" + path-exists "^5.0.0" + +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + +globals@^15.12.0: + version "15.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-15.12.0.tgz#1811872883ad8f41055b61457a130221297de5b5" + integrity sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ== + +glogg@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" + integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== + dependencies: + sparkles "^1.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graceful-fs@^4.1.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +gulp-css-base64@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/gulp-css-base64/-/gulp-css-base64-1.3.4.tgz#afca45e83401045f472c67b776d1b1514e11489f" + integrity sha512-4bdGQW0PFA6Z9zfeYlsGod9IeSPP6u6wobzixZd0w5f36aqP6Oecrb6fJCEQ4xinthH4f4OLs+8+b+Az2hOYwQ== + dependencies: + async "^1.5.0" + buffers "^0.1.1" + chalk "^1.1.1" + gulp-util "^3.0.3" + mime "^1.3.4" + request "^2.67.0" + through2 "^2.0.0" + +gulp-util@^3.0.3: + version "3.0.8" + resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" + integrity sha512-q5oWPc12lwSFS9h/4VIjG+1NuNDlJ48ywV2JKItY4Ycc/n1fXJeYPVQsfu5ZrhQi7FGSDBalwUCLar/GyHXKGw== + dependencies: + array-differ "^1.0.0" + array-uniq "^1.0.2" + beeper "^1.0.0" + chalk "^1.0.0" + dateformat "^2.0.0" + fancy-log "^1.1.0" + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash._reescape "^3.0.0" + lodash._reevaluate "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.template "^3.0.0" + minimist "^1.1.0" + multipipe "^0.1.2" + object-assign "^3.0.0" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl "^0.5.0" + +gulplog@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + integrity sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw== + dependencies: + glogg "^1.0.0" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-gulplog@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" + integrity sha512-+F4GzLjwHNNDEAJW2DC1xXfEoPkRDmUdJ7CBYw4MpqtDwOnqdImJl7GWlpqx+Wko6//J8uKTnIe4wZSv7yCqmw== + dependencies: + sparkles "^1.0.0" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +husky@^9.1.6: + version "9.1.6" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.6.tgz#e23aa996b6203ab33534bdc82306b0cf2cb07d6c" + integrity sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A== + +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +interpret@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner-eslint@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/jest-runner-eslint/-/jest-runner-eslint-2.2.1.tgz#3cb214f84eeab3848af81c5842359e82073a3aef" + integrity sha512-BSAB65hGhtr/Kmb7tSkfqFmK9LYwCMK8L1xcp+XaSToPFqr7sY1jleMZUeDhV0ITA33pW+JUCx5a02veVD2Q2w== + dependencies: + chalk "^4.0.0" + cosmiconfig "^7.0.0" + create-jest-runner "^0.11.2" + dot-prop "^6.0.1" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest-worker@^28.0.2: + version "28.1.3" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.3.tgz#7e3c4ce3fa23d1bb6accb169e7f396f98ed4bb98" + integrity sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +js2xmlparser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/js2xmlparser/-/js2xmlparser-4.0.2.tgz#2a1fdf01e90585ef2ae872a01bc169c6a8d5e60a" + integrity sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA== + dependencies: + xmlcreate "^2.0.4" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + +jsdoc-template@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/jsdoc-template/-/jsdoc-template-1.2.0.tgz#5ad0c85ed509a5de9b51537835c1762d90e75564" + integrity sha512-Njl5ROuIDCcNfdDjIFHw5URlziXwZXgcUkch9GhSlf7U/q0Et7kwDxlapZsgJ8dzSboCq9xx6MSFlkAm1WhGEw== + dependencies: + gulp-css-base64 "^1.3.4" + +jsdoc@^3.6.11: + version "3.6.11" + resolved "https://registry.yarnpkg.com/jsdoc/-/jsdoc-3.6.11.tgz#8bbb5747e6f579f141a5238cbad4e95e004458ce" + integrity sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg== + dependencies: + "@babel/parser" "^7.9.4" + "@types/markdown-it" "^12.2.3" + bluebird "^3.7.2" + catharsis "^0.9.0" + escape-string-regexp "^2.0.0" + js2xmlparser "^4.0.2" + klaw "^3.0.0" + markdown-it "^12.3.2" + markdown-it-anchor "^8.4.1" + marked "^4.0.10" + mkdirp "^1.0.4" + requizzle "^0.2.3" + strip-json-comments "^3.1.0" + taffydb "2.6.2" + underscore "~1.13.2" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@^3.0.2, jsesc@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" + integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^2.2.1, json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-3.0.0.tgz#b11bec9cf2492f06756d6e809ab73a2910259146" + integrity sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g== + dependencies: + graceful-fs "^4.1.9" + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +lcov-parse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" + integrity sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +linkify-it@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e" + integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== + dependencies: + uc.micro "^1.0.1" + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +locate-path@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" + integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== + dependencies: + p-locate "^6.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + integrity sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ== + +lodash._basetostring@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" + integrity sha512-mTzAr1aNAv/i7W43vOR/uD/aJ4ngbtsRaCubp2BfZhlGU/eORUjg/7F6X0orNMdv33JOrdgGybtvMN/po3EWrA== + +lodash._basevalues@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" + integrity sha512-H94wl5P13uEqlCg7OcNNhMQ8KvWSIyqXzOPusRgHC9DK3o54P6P3xtbXlVbRABG4q5gSmp7EDdJ0MSuW9HX6Mg== + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + integrity sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA== + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + integrity sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ== + +lodash._reescape@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" + integrity sha512-Sjlavm5y+FUVIF3vF3B75GyXrzsfYV8Dlv3L4mEpuB9leg8N6yf/7rU06iLPx9fY0Mv3khVp9p7Dx0mGV6V5OQ== + +lodash._reevaluate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" + integrity sha512-OrPwdDc65iJiBeUe5n/LIjd7Viy99bKwDdk7Z5ljfZg0uFRFlfQaCy9tZ4YMAag9WAZmlVpe1iZrkIMMSMHD3w== + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA== + +lodash._root@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + integrity sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ== + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.escape@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" + integrity sha512-n1PZMXgaaDWZDSvuNZ/8XOcYO2hOKDqZel5adtR30VKQAtoWs/5AOeFA0vPV8moiPzlqe7F4cP2tzpFewQyelQ== + dependencies: + lodash._root "^3.0.0" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + integrity sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ== + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + integrity sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ== + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + integrity sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw== + +lodash.template@>=4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.template@^3.0.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" + integrity sha512-0B4Y53I0OgHUJkt+7RmlDFWKjVAI/YUpWNiL9GQz5ORDr4ttgfQGo+phBWKFLJbBdtOwgMuUkdOHOnPg45jKmQ== + dependencies: + lodash._basecopy "^3.0.0" + lodash._basetostring "^3.0.0" + lodash._basevalues "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + lodash.keys "^3.0.0" + lodash.restparam "^3.0.0" + lodash.templatesettings "^3.0.0" + +lodash.templatesettings@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" + integrity sha512-TcrlEr31tDYnWkHFWDCV3dHYroKEXpJZ2YJYvJdhN+y4AkWMDZ5I4I8XDtUKqSAyG81N7w+I1mFEJtcED+tGqQ== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash@^4.17.15, lodash@^4.17.21, lodash@^4.17.4: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-driver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +markdown-it-anchor@^8.4.1: + version "8.6.6" + resolved "https://registry.yarnpkg.com/markdown-it-anchor/-/markdown-it-anchor-8.6.6.tgz#4a12e358c9c2167ee28cb7a5f10e29d6f1ffd7ca" + integrity sha512-jRW30YGywD2ESXDc+l17AiritL0uVaSnWsb26f+68qaW9zgbIIr1f4v2Nsvc0+s0Z2N3uX6t/yAw7BwCQ1wMsA== + +markdown-it@^12.3.2: + version "12.3.2" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90" + integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg== + dependencies: + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +marked@^4.0.10: + version "4.2.5" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.2.5.tgz#979813dfc1252cc123a79b71b095759a32f42a5d" + integrity sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.19: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@^1.3.4: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.1.0, minimist@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== + +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multipipe@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" + integrity sha512-7ZxrUybYv9NonoXgwoOqtStIu18D1c3eFZj27hqgf5kBrBF8Q+tE8V0MW8dKM5QLkQPh1JhhbKgHLY9kifov4Q== + dependencies: + duplexer2 "0.0.2" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-releases@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039" + integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ== + +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" + integrity sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-limit@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" + integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== + dependencies: + yocto-queue "^1.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-locate@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" + integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== + dependencies: + p-limit "^4.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.0.0, parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse-node-version@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" + integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-exists@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" + integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picocolors@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pirates@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-dir@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-7.0.0.tgz#8f0c08d6df4476756c5ff29b3282d0bab7517d11" + integrity sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA== + dependencies: + find-up "^6.3.0" + +platform@^1.3.3: + version "1.3.6" + resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" + integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" + integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== + +pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +psl@^1.1.28: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +pure-rand@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.1.tgz#31207dddd15d43f299fdcdb2f572df65030c19af" + integrity sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg== + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== + dependencies: + resolve "^1.20.0" + +regenerate-unicode-properties@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" + integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== + dependencies: + regenerate "^1.4.2" + +regenerate-unicode-properties@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0" + integrity sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + dependencies: + "@babel/runtime" "^7.8.4" + +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== + dependencies: + "@babel/regjsgen" "^0.8.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regexpu-core@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.1.1.tgz#b469b245594cb2d088ceebc6369dceb8c00becac" + integrity sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.2.0" + regjsgen "^0.8.0" + regjsparser "^0.11.0" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsgen@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" + integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== + +regjsparser@^0.11.0: + version "0.11.2" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.11.2.tgz#7404ad42be00226d72bcf1f003f1f441861913d8" + integrity sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA== + dependencies: + jsesc "~3.0.2" + +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== + dependencies: + jsesc "~0.5.0" + +replace-ext@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" + integrity sha512-AFBWBy9EVRTa/LhEcG8QDP3FvpwZqmvN2QFDuJswFeaVhWnZMp8q3E6Zd90SR04PlIwfGdyVjNyLPyen/ek5CQ== + +request@^2.67.0, request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +requizzle@^0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/requizzle/-/requizzle-0.2.4.tgz#319eb658b28c370f0c20f968fa8ceab98c13d27c" + integrity sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw== + dependencies: + lodash "^4.17.21" + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.1.tgz#cee884cd4e3f355660e501fa3276b27d7ffe5a20" + integrity sha512-OEJWVeimw8mgQuj3HfkNl4KqRevH7lzeQNaWRPfx0PPse7Jk6ozcsG4FKVgtzDsC1KUF+YlTHh17NcgHOPykLw== + +resolve@^1.14.2, resolve@^1.20.0: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +schema-utils@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.2.tgz#36c10abca6f7577aeae136c804b0c741edeadc99" + integrity sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.3, semver@^7.5.4, semver@^7.6.0: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +serialize-javascript@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + dependencies: + randombytes "^2.1.0" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sparkles@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" + integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +synckit@^0.9.1: + version "0.9.2" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.2.tgz#a3a935eca7922d48b9e7d6c61822ee6c3ae4ec62" + integrity sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw== + dependencies: + "@pkgr/core" "^0.1.0" + tslib "^2.6.2" + +taffydb@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/taffydb/-/taffydb-2.6.2.tgz#7cbcb64b5a141b6a2efc2c5d2c67b4e150b2a268" + integrity sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA== + +tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + +terser@^5.26.0: + version "5.36.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.36.0.tgz#8b0dbed459ac40ff7b4c9fd5a3a2029de105180e" + integrity sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +throat@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.2.tgz#51a3fbb5e11ae72e2cf74861ed5c8020f89f29fe" + integrity sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ== + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +time-stamp@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + integrity sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw== + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +ts-api-utils@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.4.0.tgz#709c6f2076e511a81557f3d07a0cbd566ae8195c" + integrity sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ== + +tsd-jsdoc@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tsd-jsdoc/-/tsd-jsdoc-2.5.0.tgz#0677aa952e1a8e3ebbb5bcf7d6e2f0301d71e151" + integrity sha512-80fcJLAiUeerg4xPftp+iEEKWUjJjHk9AvcHwJqA8Zw0R4oASdu3kT/plE/Zj19QUTz8KupyOX25zStlNJjS9g== + dependencies: + typescript "^3.2.1" + +tslib@^2.6.2: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +typescript@^3.2.1: + version "3.9.10" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.10.tgz#70f3910ac7a51ed6bef79da7800690b19bf778b8" + integrity sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q== + +typescript@^5.6.3: + version "5.6.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.3.tgz#5f3449e31c9d94febb17de03cc081dd56d81db5b" + integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== + +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + +underscore@~1.13.2: + version "1.13.6" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" + integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== + +undici-types@~6.19.8: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== + +update-browserslist-db@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +update-browserslist-db@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" + integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +v8-to-istanbul@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" + integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vinyl@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" + integrity sha512-P5zdf3WB9uzr7IFoVQ2wZTmUwHL8cMZWJGzLBNCHNZ3NB6HTMsYABtt7z8tAGIINLXyAob9B9a1yzVGMFOYKEA== + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +watchpack@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" + integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +webpack-cli@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" + colorette "^2.0.14" + commander "^10.0.1" + cross-spawn "^7.0.3" + envinfo "^7.7.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^3.1.1" + rechoir "^0.8.0" + webpack-merge "^5.7.3" + +webpack-merge@^5.7.3: + version "5.9.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.9.0.tgz#dc160a1c4cf512ceca515cc231669e9ddb133826" + integrity sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@5.96.0: + version "5.96.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.96.0.tgz#1e4dc9d1d819ff1b1f89d53e45a299ffe9231a8a" + integrity sha512-gvn84AfQ4f6vUeNWmFuRp3vGERyxK4epADKTaAo60K0EQbY/YBNQbXH3Ji/ZRK5M25O/XneAOuChF4xQZjQ4xA== + dependencies: + "@types/estree" "^1.0.6" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" + acorn "^8.14.0" + browserslist "^4.24.0" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.17.1" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.11" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" + webpack-sources "^3.2.3" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +xmlcreate@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-2.0.4.tgz#0c5ab0f99cdd02a81065fa9cd8f8ae87624889be" + integrity sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg== + +xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yaml@^1.10.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.3.1: + version "17.6.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.6.2.tgz#2e23f2944e976339a1ee00f18c77fedee8332541" + integrity sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yarpm@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/yarpm/-/yarpm-1.2.0.tgz#5baaf5589f6237426cf76f812296dcf9b4254f55" + integrity sha512-gxN4Ali09uey8EpLfbYG+bTXf1hF6TA5oAXFPpKi5Nt5aztXU9AIEksXE0lpuvC50vL4De/KIeP8JXgYOZ8KbQ== + dependencies: + command-exists "^1.2.9" + cross-spawn "^7.0.3" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yocto-queue@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" + integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==