first commit

includes a (minimal) working wrapper

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
This commit is contained in:
Dominik Csapak 2020-04-02 09:24:29 +02:00
commit eb39fafa4f
1704 changed files with 580101 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.tmp
eslint-*

67
Makefile Normal file
View File

@ -0,0 +1,67 @@
include /usr/share/dpkg/pkg-info.mk
PACKAGE=pve-eslint
GITVERSION:=$(shell git rev-parse HEAD)
BUILDDIR ?= ${PACKAGE}-${DEB_VERSION_UPSTREAM}
DEB=${PACKAGE}_${DEB_VERSION_UPSTREAM_REVISION}_all.deb
SRCDIR=src
UPSTREAM=eslint
UPSTREAMTAG=v7.0.0-alpha.3
BUILDSRC=${UPSTREAM}-${UPSTREAMTAG}
all: ${DEB}
@echo ${DEB}
.PHONY: deb
deb: ${DEB}
${DEB}: ${SRCDIR}
rm -rf ${BUILDDIR}
mkdir ${BUILDDIR}
cp -a debian ${BUILDDIR}/
cp -a ${SRCDIR}/* ${BUILDDIR}/
echo "git clone git://git.proxmox.com/git/pve-eslint.git\\ngit checkout ${GITVERSION}" > ${BUILDDIR}/debian/SOURCE
cd ${BUILDDIR}; dpkg-buildpackage -rfakeroot -b -uc -us
lintian ${DEB}
@echo ${DEB}
.PHONY: download
download:
rm -rf ${UPSTREAM}.tmp ${UPSTREAM}
git clone -b ${UPSTREAMTAG} --depth 1 https://github.com/eslint/eslint ${UPSTREAM}.tmp
rm -rf ${UPSTREAM}.tmp/.git
find ${UPSTREAM}.tmp/ -type f -name '.gitignore' -delete
mv ${UPSTREAM}.tmp ${UPSTREAM}
# NOTE: needs npm installed, downloads packages from npm
.PHONY: buildupstream
buildupstream: ${BUILDSRC}
cp ${BUILDSRC}/build/eslint.js ${SRCDIR}/eslint.js
${BUILDSRC}: ${UPSTREAM} patches
rm -rf $@
mkdir $@.tmp
rsync -ra ${UPSTREAM}/ $@.tmp
cd $@.tmp; ln -s ../patches patches
cd $@.tmp; quilt push -a
cd $@.tmp; rm -rf .pc ./patches
mv $@.tmp $@
cd $@; npm install
cd $@; npm run webpack
.PHONY: upload
upload: ${DEB}
tar cf - ${DEB} | ssh -X repoman@repo.proxmox.com -- upload --product pmg,pve --dist buster
.PHONY: distclean
distclean: clean
.PHONY: clean
clean:
rm -rf *~ debian/*~ *.deb ${BUILDSRC} ${BUILDSRC}.tmp ${UPSTREAM}.tmp ${BUILDDIR} *.changes *.dsc *.buildinfo
.PHONY: dinstall
dinstall: deb
dpkg -i ${DEB}

6
debian/changelog vendored Normal file
View File

@ -0,0 +1,6 @@
pve-eslint (1.0-1) unstable; urgency=low
* first version
-- Proxmox Support Team <support@proxmox.com> Thu, 02 Apr 2020 09:16:33 +0200

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
10

12
debian/control vendored Normal file
View File

@ -0,0 +1,12 @@
Source: pve-eslint
Section: devel
Priority: optional
Maintainer: Proxmox Support Team <support@proxmox.com>
Build-Depends: debhelper (>= 7.0.0~)
Package: pve-eslint
Architecture: all
Depends: node-commander, node-colors, nodejs
Description: ESLint for Proxmox Virtual Environment development
This package contains a version of eslint used to develop the
Proxmox Virtual Environment GUI.

40
debian/copyright vendored Normal file
View File

@ -0,0 +1,40 @@
Copyright (C) 2020 Proxmox Server Solutions GmbH
This software is written by Proxmox Server Solutions GmbH <support@proxmox.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-------------
eslint
Copyright JS Foundation and other contributors, https://js.foundation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

4
debian/rules vendored Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/make -f
%:
dh $@

9
eslint/.codeclimate.yml Normal file
View File

@ -0,0 +1,9 @@
languages:
JavaScript: true
exclude_paths:
- tests/**
engines:
eslint:
enabled: true

18
eslint/.editorconfig Normal file
View File

@ -0,0 +1,18 @@
root = true
[*]
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
end_of_line = lf
insert_final_newline = true
[docs/rules/linebreak-style.md]
end_of_line = disabled
[{docs/rules/{indent.md,no-mixed-spaces-and-tabs.md}]
indent_style = disabled
indent_size = disabled
[docs/rules/no-trailing-spaces.md]
trim_trailing_whitespace = false

12
eslint/.eslintignore Normal file
View File

@ -0,0 +1,12 @@
/build/**
/coverage/**
/docs/**
/jsdoc/**
/templates/**
/tests/bench/**
/tests/fixtures/**
/tests/performance/**
/tmp/**
/tools/internal-rules/node_modules/**
test.js
!.eslintrc.js

190
eslint/.eslintrc.js Normal file
View File

@ -0,0 +1,190 @@
"use strict";
const internalFiles = [
"**/cli-engine/**/*",
"**/init/**/*",
"**/linter/**/*",
"**/rule-tester/**/*",
"**/rules/**/*",
"**/source-code/**/*"
];
module.exports = {
root: true,
plugins: [
"eslint-plugin",
"internal-rules"
],
extends: [
"eslint",
"plugin:eslint-plugin/recommended"
],
parserOptions: {
ecmaVersion: 2020
},
rules: {
"eslint-plugin/consistent-output": "error",
"eslint-plugin/no-deprecated-context-methods": "error",
"eslint-plugin/prefer-output-null": "error",
"eslint-plugin/prefer-placeholders": "error",
"eslint-plugin/report-message-format": ["error", "[^a-z].*\\.$"],
"eslint-plugin/require-meta-docs-description": "error",
"eslint-plugin/require-meta-type": "error",
"eslint-plugin/test-case-property-ordering": [
"error",
// https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/issues/79
[
"filename",
"code",
"output",
"options",
"parser",
"parserOptions",
"globals",
"env",
"errors"
]
],
"eslint-plugin/test-case-shorthand-strings": "error",
"internal-rules/multiline-comment-style": "error"
},
overrides: [
{
files: ["lib/rules/*", "tools/internal-rules/*"],
excludedFiles: ["index.js"],
rules: {
"internal-rules/no-invalid-meta": "error"
/*
* TODO: enable it when all the rules using meta.messages
* "internal-rules/consistent-meta-messages": "error"
*/
}
},
{
files: ["lib/rules/*"],
excludedFiles: ["index.js"],
rules: {
"internal-rules/consistent-docs-url": "error"
}
},
{
files: ["tests/**/*"],
env: { mocha: true },
rules: {
"no-restricted-syntax": ["error", {
selector: "CallExpression[callee.object.name='assert'][callee.property.name='doesNotThrow']",
message: "`assert.doesNotThrow()` should be replaced with a comment next to the code."
}]
}
},
// Restrict relative path imports
{
files: ["lib/*"],
rules: {
"no-restricted-modules": ["error", {
patterns: [
...internalFiles
]
}]
}
},
{
files: ["lib/cli-engine/**/*"],
rules: {
"no-restricted-modules": ["error", {
patterns: [
...internalFiles,
"**/init"
]
}]
}
},
{
files: ["lib/init/**/*"],
rules: {
"no-restricted-modules": ["error", {
patterns: [
...internalFiles,
"**/rule-tester"
]
}]
}
},
{
files: ["lib/linter/**/*"],
rules: {
"no-restricted-modules": ["error", {
patterns: [
...internalFiles,
"fs",
"**/cli-engine",
"**/init",
"**/rule-tester"
]
}]
}
},
{
files: ["lib/rules/**/*"],
rules: {
"no-restricted-modules": ["error", {
patterns: [
...internalFiles,
"fs",
"**/cli-engine",
"**/init",
"**/linter",
"**/rule-tester",
"**/source-code"
]
}]
}
},
{
files: ["lib/shared/**/*"],
rules: {
"no-restricted-modules": ["error", {
patterns: [
...internalFiles,
"**/cli-engine",
"**/init",
"**/linter",
"**/rule-tester",
"**/source-code"
]
}]
}
},
{
files: ["lib/source-code/**/*"],
rules: {
"no-restricted-modules": ["error", {
patterns: [
...internalFiles,
"fs",
"**/cli-engine",
"**/init",
"**/linter",
"**/rule-tester",
"**/rules"
]
}]
}
},
{
files: ["lib/rule-tester/**/*"],
rules: {
"no-restricted-modules": ["error", {
patterns: [
...internalFiles,
"**/cli-engine",
"**/init"
]
}]
}
}
]
};

8
eslint/.gitattributes vendored Normal file
View File

@ -0,0 +1,8 @@
# Convert text file line endings to lf
* text=auto
*.js text eol=lf
# The test fixtures are text files.
/tests/fixtures/**/* text eol=lf
/tests/fixtures/ignored-paths/crlf/.eslintignore text eol=crlf

2
eslint/.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,2 @@
github: eslint
open_collective: eslint

53
eslint/.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,53 @@
<!--
ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
This template is for bug reports. If you are here for another reason, please see below:
1. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint
Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->
**Tell us about your environment**
<!--
If you are using ESLint v6.5.0 or later, you can run ESLint with the `--env-info` flag and paste the output here.
-->
* **ESLint Version:**
* **Node Version:**
* **npm Version:**
**What parser (default, Babel-ESLint, etc.) are you using?**
**Please show your full configuration:**
<details>
<summary>Configuration</summary>
<!-- Paste your configuration below: -->
```js
```
</details>
**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**
<!-- Paste the source code below: -->
```js
```
<!-- Paste the command you used to run ESLint: -->
```bash
```
**What did you expect to happen?**
**What actually happened? Please include the actual, raw output from ESLint.**

View File

@ -0,0 +1,65 @@
---
name: "\U0001F41E Bug report"
about: Report an issue with ESLint or rules bundled with ESLint
title: ''
labels: bug, triage
assignees: ''
---
<!--
ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
This template is for bug reports. If you are here for another reason, please see below:
1. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint
Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->
**Tell us about your environment**
<!--
If you are using ESLint v6.5.0 or later, you can run ESLint with the `--env-info` flag and paste the output here.
-->
* **ESLint Version:**
* **Node Version:**
* **npm Version:**
**What parser (default, Babel-ESLint, etc.) are you using?**
**Please show your full configuration:**
<details>
<summary>Configuration</summary>
<!-- Paste your configuration below: -->
```js
```
</details>
**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**
<!-- Paste the source code below: -->
```js
```
<!-- Paste the command you used to run ESLint: -->
```bash
```
**What did you expect to happen?**
**What actually happened? Please include the actual, raw output from ESLint.**
**Are you willing to submit a pull request to fix this bug?**

32
eslint/.github/ISSUE_TEMPLATE/CHANGE.md vendored Normal file
View File

@ -0,0 +1,32 @@
---
name: "\U0001F4DD Non-rule change request"
about: Request a change that is not a bug fix, rule change, or new rule
title: ''
labels: enhancement, triage, core
assignees: ''
---
<!--
ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
This template is for requesting a change that is not a bug fix, rule change, or new rule. If you are here for another reason, please see below:
1. To report a bug: https://eslint.org/docs/developer-guide/contributing/reporting-bugs
2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
3. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint
Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->
**The version of ESLint you are using.**
**The problem you want to solve.**
**Your take on the correct solution to problem.**
**Are you willing to submit a pull request to implement this change?**

View File

@ -0,0 +1,42 @@
---
name: "\U0001F680 New rule proposal"
about: Propose a new rule to be added to ESLint
title: ''
labels: triage, rule, feature
assignees: ''
---
<!--
ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
This template is for new rule proposals. If you are proposing a new rule, please continue on. If you are here for another reason, please see below:
1. To report a bug: https://eslint.org/docs/developer-guide/contributing/reporting-bugs
2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint
Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->
**Please describe what the rule should do:**
**What category of rule is this? (place an "X" next to just one item)**
[ ] Warns about a potential error (problem)
[ ] Suggests an alternate way of doing something (suggestion)
[ ] Enforces code style (layout)
[ ] Other (please specify:)
**Provide 2-3 code examples that this rule will warn about:**
<!-- Put your code examples here -->
```js
```
**Why should this rule be included in ESLint (instead of a plugin)?**
**Are you willing to submit a pull request to implement this rule?**

View File

@ -0,0 +1,25 @@
---
name: "⛔ Question"
about: Please go to https://gitter.im/eslint/eslint
title: ''
labels: ''
assignees: ''
---
<!--
ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
Please do not use GitHub for asking questions. Instead,
please visit our chatroom:
https://gitter.im/eslint/eslint
Or our mailing list:
https://groups.google.com/group/eslint
Thanks in advance for helping us keep the issue tracker
clean!
-->

View File

@ -0,0 +1,40 @@
---
name: "\U0001F4DD Rule change request"
about: Request a change to an existing rule
title: ''
labels: enhancement, triage, rule
assignees: ''
---
<!--
ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
This template is for requesting a rule change. If you are here for another reason, please see below:
1. To report a bug: https://eslint.org/docs/developer-guide/contributing/reporting-bugs
2. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint
Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->
**What rule do you want to change?**
**Does this change cause the rule to produce more or fewer warnings?**
**How will the change be implemented? (New option, new default behavior, etc.)?**
**Please provide some example code that this change will affect:**
<!-- Put your code examples here -->
```js
```
**What does the rule currently do for this code?**
**What will the rule do after it's changed?**
**Are you willing to submit a pull request to implement this change?**

View File

@ -0,0 +1,22 @@
---
name: "⛔ Security issue"
about: Please file security issues at https://hackerone.com/eslint
title: ''
labels: ''
assignees: ''
---
<!--
ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
STOP! Please do not use GitHub for filing security issues.
Doing so is insecure and may put other ESLint users at risk.
To securely notify us of a security issue, please go to:
https://hackerone.com/eslint
Thanks in advance for helping us keep the ESLint community
safe and secure.
-->

42
eslint/.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,42 @@
<!--
Thank you for contributing!
ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->
#### Prerequisites checklist
- [ ] I have read the [contributing guidelines](https://github.com/eslint/eslint/blob/master/CONTRIBUTING.md).
- [ ] The team has reached consensus on the changes proposed in this pull request. If not, I understand that the evaluation process will begin with this pull request and won't be merged until the team has reached consensus.
#### What is the purpose of this pull request? (put an "X" next to an item)
[ ] Documentation update
[ ] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:
<!--
If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->
<!--
Please ensure your pull request is ready:
- Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
- Include tests for this change
- Update documentation for this change (if appropriate)
-->
<!--
The following is required for all pull requests:
-->
#### What changes did you make? (Give an overview)
#### Is there anything you'd like reviewers to focus on?

67
eslint/.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,67 @@
name: CI
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
verify_files:
name: Verify Files
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- name: Install Packages
run: npm install
- name: Lint Files
run: node Makefile lint
- name: Check Rule Files
run: node Makefile checkRuleFiles
- name: Check Licenses
run: node Makefile checkLicenses
test_on_node:
name: Test
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
node: [13.x, 12.x, 10.x, "10.12.0"]
exclude:
- os: windows-latest
node: "10.12.0"
- os: windows-latest
node: 10.x
- os: windows-latest
node: 13.x
- os: macOS-latest
node: "10.12.0"
- os: macOS-latest
node: 10.x
- os: macOS-latest
node: 13.x
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
- name: Install Packages
run: npm install
- name: Test
run: node Makefile mocha
- name: Fuzz Test
run: node Makefile fuzz
test_on_browser:
name: Browser Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- name: Install Packages
run: npm install
- name: Test
run: node Makefile karma
- name: Fuzz Test
run: node Makefile fuzz

21
eslint/.markdownlint.yml Normal file
View File

@ -0,0 +1,21 @@
default: true
# Exclusions for deliberate/widespread violations
MD001: false # Header levels should only increment by one level at a time
MD002: false # First header should be a h1 header
MD007: # Unordered list indentation
indent: 4
MD012: false # Multiple consecutive blank lines
MD013: false # Line length
MD014: false # Dollar signs used before commands without showing output
MD019: false # Multiple spaces after hash on atx style header
MD021: false # Multiple spaces inside hashes on closed atx style header
MD024: false # Multiple headers with the same content
MD026: false # Trailing punctuation in header
MD029: false # Ordered list item prefix
MD030: false # Spaces after list markers
MD033: false # Allow inline HTML
MD034: false # Bare URL used
MD040: false # Fenced code blocks should have a language specified
MD041: false # First line in file should be a top level header
MD046: false # Code block style

1
eslint/.npmrc Normal file
View File

@ -0,0 +1 @@
package-lock = false

13
eslint/.nycrc Normal file
View File

@ -0,0 +1,13 @@
{
"include": [
"bin/**/*.js",
"conf/**/*.js",
"lib/**/*.js"
],
"reporter": [
"lcov",
"text-summary",
"cobertura"
],
"sourceMap": true
}

5736
eslint/CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
This project adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).

27
eslint/CONTRIBUTING.md Normal file
View File

@ -0,0 +1,27 @@
# Contributing
Please be sure to read the contribution guidelines before making or requesting a change.
## Code of Conduct
This project adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct). We kindly request that you read over our code of conduct before contributing.
## Filing Issues
Before filing an issue, please be sure to read the guidelines for what you're reporting:
* [Bug Report](https://eslint.org/docs/developer-guide/contributing/reporting-bugs)
* [Propose a New Rule](https://eslint.org/docs/developer-guide/contributing/new-rules)
* [Proposing a Rule Change](https://eslint.org/docs/developer-guide/contributing/rule-changes)
* [Request a Change](https://eslint.org/docs/developer-guide/contributing/changes)
To report a security vulnerability in ESLint, please use our [HackerOne program](https://hackerone.com/eslint).
## Contributing Code
Please sign our [Contributor License Agreement](https://cla.js.foundation/eslint/eslint) and read over the [Pull Request Guidelines](https://eslint.org/docs/developer-guide/contributing/pull-requests).
## Full Documentation
Our full contribution guidelines can be found at:
https://eslint.org/docs/developer-guide/contributing/

19
eslint/LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright JS Foundation and other contributors, https://js.foundation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

1092
eslint/Makefile.js Normal file

File diff suppressed because it is too large Load Diff

260
eslint/README.md Normal file
View File

@ -0,0 +1,260 @@
[![NPM version](https://img.shields.io/npm/v/eslint.svg)](https://www.npmjs.com/package/eslint)
[![Downloads](https://img.shields.io/npm/dm/eslint.svg)](https://www.npmjs.com/package/eslint)
[![Build Status](https://github.com/eslint/eslint/workflows/CI/badge.svg)](https://github.com/eslint/eslint/actions)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint?ref=badge_shield)
<br />
[![Open Collective Backers](https://img.shields.io/opencollective/backers/eslint)](https://opencollective.com/eslint)
[![Open Collective Sponsors](https://img.shields.io/opencollective/sponsors/eslint)](https://opencollective.com/eslint)
[![Join the chat at https://gitter.im/eslint/eslint](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/eslint/eslint?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Follow us on Twitter](https://img.shields.io/twitter/follow/geteslint?label=Follow&style=social)](https://twitter.com/intent/user?screen_name=geteslint)
# ESLint
[Website](https://eslint.org) |
[Configuring](https://eslint.org/docs/user-guide/configuring) |
[Rules](https://eslint.org/docs/rules/) |
[Contributing](https://eslint.org/docs/developer-guide/contributing) |
[Reporting Bugs](https://eslint.org/docs/developer-guide/contributing/reporting-bugs) |
[Code of Conduct](https://js.foundation/community/code-of-conduct) |
[Twitter](https://twitter.com/geteslint) |
[Mailing List](https://groups.google.com/group/eslint) |
[Chat Room](https://gitter.im/eslint/eslint)
ESLint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code. In many ways, it is similar to JSLint and JSHint with a few exceptions:
* ESLint uses [Espree](https://github.com/eslint/espree) for JavaScript parsing.
* ESLint uses an AST to evaluate patterns in code.
* ESLint is completely pluggable, every single rule is a plugin and you can add more at runtime.
## Table of Contents
1. [Installation and Usage](#installation-and-usage)
2. [Configuration](#configuration)
3. [Code of Conduct](#code-of-conduct)
4. [Filing Issues](#filing-issues)
5. [Frequently Asked Questions](#faq)
6. [Releases](#releases)
7. [Semantic Versioning Policy](#semantic-versioning-policy)
8. [License](#license)
9. [Team](#team)
10. [Sponsors](#sponsors)
11. [Technology Sponsors](#technology-sponsors)
## <a name="installation-and-usage"></a>Installation and Usage
Prerequisites: [Node.js](https://nodejs.org/) (`^10.12.0`, or `>=12.0.0`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
You can install ESLint using npm:
```
$ npm install eslint --save-dev
```
You should then set up a configuration file:
```
$ ./node_modules/.bin/eslint --init
```
After that, you can run ESLint on any file or directory like this:
```
$ ./node_modules/.bin/eslint yourfile.js
```
## <a name="configuration"></a>Configuration
After running `eslint --init`, you'll have a `.eslintrc` file in your directory. In it, you'll see some rules configured like this:
```json
{
"rules": {
"semi": ["error", "always"],
"quotes": ["error", "double"]
}
}
```
The names `"semi"` and `"quotes"` are the names of [rules](https://eslint.org/docs/rules) in ESLint. The first value is the error level of the rule and can be one of these values:
* `"off"` or `0` - turn the rule off
* `"warn"` or `1` - turn the rule on as a warning (doesn't affect exit code)
* `"error"` or `2` - turn the rule on as an error (exit code will be 1)
The three error levels allow you fine-grained control over how ESLint applies rules (for more configuration options and details, see the [configuration docs](https://eslint.org/docs/user-guide/configuring)).
## <a name="code-of-conduct"></a>Code of Conduct
ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
## <a name="filing-issues"></a>Filing Issues
Before filing an issue, please be sure to read the guidelines for what you're reporting:
* [Bug Report](https://eslint.org/docs/developer-guide/contributing/reporting-bugs)
* [Propose a New Rule](https://eslint.org/docs/developer-guide/contributing/new-rules)
* [Proposing a Rule Change](https://eslint.org/docs/developer-guide/contributing/rule-changes)
* [Request a Change](https://eslint.org/docs/developer-guide/contributing/changes)
## <a name="faq"></a>Frequently Asked Questions
### I'm using JSCS, should I migrate to ESLint?
Yes. [JSCS has reached end of life](https://eslint.org/blog/2016/07/jscs-end-of-life) and is no longer supported.
We have prepared a [migration guide](https://eslint.org/docs/user-guide/migrating-from-jscs) to help you convert your JSCS settings to an ESLint configuration.
We are now at or near 100% compatibility with JSCS. If you try ESLint and believe we are not yet compatible with a JSCS rule/configuration, please create an issue (mentioning that it is a JSCS compatibility issue) and we will evaluate it as per our normal process.
### Does Prettier replace ESLint?
No, ESLint does both traditional linting (looking for problematic patterns) and style checking (enforcement of conventions). You can use ESLint for everything, or you can combine both using Prettier to format your code and ESLint to catch possible errors.
### Why can't ESLint find my plugins?
* Make sure your plugins (and ESLint) are both in your project's `package.json` as devDependencies (or dependencies, if your project uses ESLint at runtime).
* Make sure you have run `npm install` and all your dependencies are installed.
* Make sure your plugins' peerDependencies have been installed as well. You can use `npm view eslint-plugin-myplugin peerDependencies` to see what peer dependencies `eslint-plugin-myplugin` has.
### Does ESLint support JSX?
Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [configuration](https://eslint.org/docs/user-guide/configuring)). Please note that supporting JSX syntax *is not* the same as supporting React. React applies specific semantics to JSX syntax that ESLint doesn't recognize. We recommend using [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) if you are using React and want React semantics.
### What ECMAScript versions does ESLint support?
ESLint has full support for ECMAScript 3, 5 (default), 2015, 2016, 2017, 2018, and 2019. You can set your desired ECMAScript syntax (and other settings, like global variables or your target environments) through [configuration](https://eslint.org/docs/user-guide/configuring).
### What about experimental features?
ESLint's parser only officially supports the latest final ECMAScript standard. We will make changes to core rules in order to avoid crashes on stage 3 ECMAScript syntax proposals (as long as they are implemented using the correct experimental ESTree syntax). We may make changes to core rules to better work with language extensions (such as JSX, Flow, and TypeScript) on a case-by-case basis.
In other cases (including if rules need to warn on more or fewer cases due to new syntax, rather than just not crashing), we recommend you use other parsers and/or rule plugins. If you are using Babel, you can use the [babel-eslint](https://github.com/babel/babel-eslint) parser and [eslint-plugin-babel](https://github.com/babel/eslint-plugin-babel) to use any option available in Babel.
Once a language feature has been adopted into the ECMAScript standard (stage 4 according to the [TC39 process](https://tc39.github.io/process-document/)), we will accept issues and pull requests related to the new feature, subject to our [contributing guidelines](https://eslint.org/docs/developer-guide/contributing). Until then, please use the appropriate parser and plugin(s) for your experimental feature.
### Where to ask for help?
Join our [Mailing List](https://groups.google.com/group/eslint) or [Chatroom](https://gitter.im/eslint/eslint).
## <a name="releases"></a>Releases
We have scheduled releases every two weeks on Friday or Saturday. You can follow a [release issue](https://github.com/eslint/eslint/issues?q=is%3Aopen+is%3Aissue+label%3Arelease) for updates about the scheduling of any particular release.
## <a name="semantic-versioning-policy"></a>Semantic Versioning Policy
ESLint follows [semantic versioning](https://semver.org). However, due to the nature of ESLint as a code quality tool, it's not always clear when a minor or major version bump occurs. To help clarify this for everyone, we've defined the following semantic versioning policy for ESLint:
* Patch release (intended to not break your lint build)
* A bug fix in a rule that results in ESLint reporting fewer errors.
* A bug fix to the CLI or core (including formatters).
* Improvements to documentation.
* Non-user-facing changes such as refactoring code, adding, deleting, or modifying tests, and increasing test coverage.
* Re-releasing after a failed release (i.e., publishing a release that doesn't work for anyone).
* Minor release (might break your lint build)
* A bug fix in a rule that results in ESLint reporting more errors.
* A new rule is created.
* A new option to an existing rule that does not result in ESLint reporting more errors by default.
* An existing rule is deprecated.
* A new CLI capability is created.
* New capabilities to the public API are added (new classes, new methods, new arguments to existing methods, etc.).
* A new formatter is created.
* `eslint:recommended` is updated and will result in strictly fewer errors (e.g., rule removals).
* Major release (likely to break your lint build)
* `eslint:recommended` is updated and may result in new errors (e.g., rule additions, most rule option updates).
* A new option to an existing rule that results in ESLint reporting more errors by default.
* An existing formatter is removed.
* Part of the public API is removed or changed in an incompatible way.
According to our policy, any minor update may report more errors than the previous release (ex: from a bug fix). As such, we recommend using the tilde (`~`) in `package.json` e.g. `"eslint": "~3.1.0"` to guarantee the results of your builds.
## <a name="license"></a>License
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Feslint%2Feslint?ref=badge_large)
## <a name="team"></a>Team
These folks keep the project moving and are resources for help.
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
<!--teamstart-->
### Technical Steering Committee (TSC)
The people who manage releases, review feature requests, and meet regularly to ensure ESLint is properly maintained.
<table><tbody><tr><td align="center" valign="top" width="11%">
<a href="https://github.com/nzakas">
<img src="https://github.com/nzakas.png?s=75" width="75" height="75"><br />
Nicholas C. Zakas
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/btmills">
<img src="https://github.com/btmills.png?s=75" width="75" height="75"><br />
Brandon Mills
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/mysticatea">
<img src="https://github.com/mysticatea.png?s=75" width="75" height="75"><br />
Toru Nagashima
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/kaicataldo">
<img src="https://github.com/kaicataldo.png?s=75" width="75" height="75"><br />
Kai Cataldo
</a>
</td></tr></tbody></table>
### Reviewers
The people who review and implement new features.
<table><tbody><tr><td align="center" valign="top" width="11%">
<a href="https://github.com/aladdin-add">
<img src="https://github.com/aladdin-add.png?s=75" width="75" height="75"><br />
薛定谔的猫
</a>
</td></tr></tbody></table>
### Committers
The people who review and fix bugs and help triage issues.
<table><tbody><tr><td align="center" valign="top" width="11%">
<a href="https://github.com/g-plane">
<img src="https://github.com/g-plane.png?s=75" width="75" height="75"><br />
Pig Fang
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/yeonjuan">
<img src="https://github.com/yeonjuan.png?s=75" width="75" height="75"><br />
YeonJuan
</a>
</td><td align="center" valign="top" width="11%">
<a href="https://github.com/mdjermanovic">
<img src="https://github.com/mdjermanovic.png?s=75" width="75" height="75"><br />
Milos Djermanovic
</a>
</td></tr></tbody></table>
<!--teamend-->
## <a name="sponsors"></a>Sponsors
The following companies, organizations, and individuals support ESLint's ongoing maintenance and development. [Become a Sponsor](https://opencollective.com/eslint) to get your logo on our README and website.
<!-- NOTE: This section is autogenerated. Do not manually edit.-->
<!--sponsorsstart-->
<h3>Gold Sponsors</h3>
<p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://magiclab.co/?utm_source=eslint"><img src="https://images.opencollective.com/magiclab/bbf6345/logo.png" alt="MagicLab" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a></p><h3>Silver Sponsors</h3>
<p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
<p><a href="https://www.kasinot.fi"><img src="https://images.opencollective.com/kasinot-fi/e09aa2e/logo.png" alt="Kasinot.fi" height="32"></a> <a href="https://www.pelisivut.com"><img src="https://images.opencollective.com/pelisivut/04f08f2/logo.png" alt="Pelisivut" height="32"></a> <a href="https://www.nettikasinot.org"><img src="https://images.opencollective.com/nettikasinot-org/bbd887f/logo.png" alt="Nettikasinot.org" height="32"></a> <a href="https://www.bonus.com.de/freispiele"><img src="https://images.opencollective.com/bonusfinder-deutschland/646169e/logo.png" alt="BonusFinder Deutschland" height="32"></a> <a href="https://medium.com/@niksundin/best-web-design-companies-1872e445775f"><img src="https://images.opencollective.com/top-web-design-agencies/d92d747/logo.png" alt="Top Web Design Agencies" height="32"></a> <a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
<!--sponsorsend-->
## <a name="technology-sponsors"></a>Technology Sponsors
* Site search ([eslint.org](https://eslint.org)) is sponsored by [Algolia](https://www.algolia.com)

1
eslint/SUPPORT.md Normal file
View File

@ -0,0 +1 @@
If you have a question about how to use ESLint, please ask it in our [Gitter channel](https://gitter.im/eslint/eslint).

108
eslint/bin/eslint.js Executable file
View File

@ -0,0 +1,108 @@
#!/usr/bin/env node
/**
* @fileoverview Main CLI that is run via the eslint command.
* @author Nicholas C. Zakas
*/
/* eslint no-console:off */
"use strict";
// to use V8's code cache to speed up instantiation time
require("v8-compile-cache");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
const useStdIn = process.argv.includes("--stdin"),
init = process.argv.includes("--init"),
debug = process.argv.includes("--debug");
// must do this initialization *before* other requires in order to work
if (debug) {
require("debug").enable("eslint:*,-eslint:code-path");
}
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
// now we can safely include the other modules that use debug
const path = require("path"),
fs = require("fs"),
cli = require("../lib/cli");
//------------------------------------------------------------------------------
// Execution
//------------------------------------------------------------------------------
process.once("uncaughtException", err => {
// lazy load
const lodash = require("lodash");
if (typeof err.messageTemplate === "string" && err.messageTemplate.length > 0) {
const template = lodash.template(fs.readFileSync(path.resolve(__dirname, `../messages/${err.messageTemplate}.txt`), "utf-8"));
const pkg = require("../package.json");
console.error("\nOops! Something went wrong! :(");
console.error(`\nESLint: ${pkg.version}.\n\n${template(err.messageData || {})}`);
} else {
console.error(err.stack);
}
process.exitCode = 2;
});
if (useStdIn) {
/*
* Note: See
* - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin
* - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io
* - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html
* - https://github.com/nodejs/node/issues/7439 (historical)
*
* On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems
* to read 4096 bytes before blocking and never drains to read further data.
*
* The investigation on the Emacs thread indicates:
*
* > Emacs on MS-Windows uses pipes to communicate with subprocesses; a
* > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than
* > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for
* > the subprocess to read its end of the pipe, at which time Emacs will
* > write the rest of the stuff.
*
* Using the nodejs code example for reading from stdin.
*/
let contents = "",
chunk = "";
process.stdin.setEncoding("utf8");
process.stdin.on("readable", () => {
// Use a loop to make sure we read all available data.
while ((chunk = process.stdin.read()) !== null) {
contents += chunk;
}
});
process.stdin.on("end", () => {
process.exitCode = cli.execute(process.argv, contents, "utf8");
});
} else if (init) {
const configInit = require("../lib/init/config-initializer");
configInit.initializeConfig().then(() => {
process.exitCode = 0;
}).catch(err => {
process.exitCode = 1;
console.error(err.message);
console.error(err.stack);
});
} else {
process.exitCode = cli.execute(process.argv);
}

View File

@ -0,0 +1,40 @@
{
"categories": [
{ "name": "Possible Errors", "description": "These rules relate to possible syntax or logic errors in JavaScript code:" },
{ "name": "Best Practices", "description": "These rules relate to better ways of doing things to help you avoid problems:" },
{ "name": "Strict Mode", "description": "These rules relate to strict mode directives:" },
{ "name": "Variables", "description": "These rules relate to variable declarations:" },
{ "name": "Node.js and CommonJS", "description": "These rules relate to code running in Node.js, or in browsers with CommonJS:" },
{ "name": "Stylistic Issues", "description": "These rules relate to style guidelines, and are therefore quite subjective:" },
{ "name": "ECMAScript 6", "description": "These rules relate to ES6, also known as ES2015:" }
],
"deprecated": {
"name": "Deprecated",
"description": "These rules have been deprecated in accordance with the <a href=\"/docs/user-guide/rule-deprecation\">deprecation policy</a>, and replaced by newer rules:",
"rules": []
},
"removed": {
"name": "Removed",
"description": "These rules from older versions of ESLint (before the <a href=\"/docs/user-guide/rule-deprecation\">deprecation policy</a> existed) have been replaced by newer rules:",
"rules": [
{ "removed": "generator-star", "replacedBy": ["generator-star-spacing"] },
{ "removed": "global-strict", "replacedBy": ["strict"] },
{ "removed": "no-arrow-condition", "replacedBy": ["no-confusing-arrow", "no-constant-condition"] },
{ "removed": "no-comma-dangle", "replacedBy": ["comma-dangle"] },
{ "removed": "no-empty-class", "replacedBy": ["no-empty-character-class"] },
{ "removed": "no-empty-label", "replacedBy": ["no-labels"] },
{ "removed": "no-extra-strict", "replacedBy": ["strict"] },
{ "removed": "no-reserved-keys", "replacedBy": ["quote-props"] },
{ "removed": "no-space-before-semi", "replacedBy": ["semi-spacing"] },
{ "removed": "no-wrap-func", "replacedBy": ["no-extra-parens"] },
{ "removed": "space-after-function-name", "replacedBy": ["space-before-function-paren"] },
{ "removed": "space-after-keywords", "replacedBy": ["keyword-spacing"] },
{ "removed": "space-before-function-parentheses", "replacedBy": ["space-before-function-paren"] },
{ "removed": "space-before-keywords", "replacedBy": ["keyword-spacing"] },
{ "removed": "space-in-brackets", "replacedBy": ["object-curly-spacing", "array-bracket-spacing"] },
{ "removed": "space-return-throw-case", "replacedBy": ["keyword-spacing"] },
{ "removed": "space-unary-word-ops", "replacedBy": ["space-unary-ops"] },
{ "removed": "spaced-line-comment", "replacedBy": ["spaced-comment"] }
]
}
}

View File

@ -0,0 +1,81 @@
/**
* @fileoverview Defines a schema for configs.
* @author Sylvan Mably
*/
"use strict";
const baseConfigProperties = {
$schema: { type: "string" },
env: { type: "object" },
extends: { $ref: "#/definitions/stringOrStrings" },
globals: { type: "object" },
overrides: {
type: "array",
items: { $ref: "#/definitions/overrideConfig" },
additionalItems: false
},
parser: { type: ["string", "null"] },
parserOptions: { type: "object" },
plugins: { type: "array" },
processor: { type: "string" },
rules: { type: "object" },
settings: { type: "object" },
noInlineConfig: { type: "boolean" },
reportUnusedDisableDirectives: { type: "boolean" },
ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
};
const configSchema = {
definitions: {
stringOrStrings: {
oneOf: [
{ type: "string" },
{
type: "array",
items: { type: "string" },
additionalItems: false
}
]
},
stringOrStringsRequired: {
oneOf: [
{ type: "string" },
{
type: "array",
items: { type: "string" },
additionalItems: false,
minItems: 1
}
]
},
// Config at top-level.
objectConfig: {
type: "object",
properties: {
root: { type: "boolean" },
ignorePatterns: { $ref: "#/definitions/stringOrStrings" },
...baseConfigProperties
},
additionalProperties: false
},
// Config in `overrides`.
overrideConfig: {
type: "object",
properties: {
excludedFiles: { $ref: "#/definitions/stringOrStrings" },
files: { $ref: "#/definitions/stringOrStringsRequired" },
...baseConfigProperties
},
required: ["files"],
additionalProperties: false
}
},
$ref: "#/definitions/objectConfig"
};
module.exports = configSchema;

View File

@ -0,0 +1,31 @@
/**
* @fileoverview Default CLIEngineOptions.
* @author Ian VanSchooten
*/
"use strict";
module.exports = {
configFile: null,
baseConfig: false,
rulePaths: [],
useEslintrc: true,
envs: [],
globals: [],
extensions: null,
ignore: true,
ignorePath: void 0,
cache: false,
/*
* in order to honor the cacheFile option if specified
* this option should not have a default value otherwise
* it will always be used
*/
cacheLocation: "",
cacheFile: ".eslintcache",
fix: false,
allowInlineConfig: true,
reportUnusedDisableDirectives: void 0,
globInputPaths: true
};

168
eslint/conf/environments.js Normal file
View File

@ -0,0 +1,168 @@
/**
* @fileoverview Defines environment settings and globals.
* @author Elan Shanker
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const globals = require("globals");
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
/**
* Get the object that has difference.
* @param {Record<string,boolean>} current The newer object.
* @param {Record<string,boolean>} prev The older object.
* @returns {Record<string,boolean>} The difference object.
*/
function getDiff(current, prev) {
const retv = {};
for (const [key, value] of Object.entries(current)) {
if (!Object.hasOwnProperty.call(prev, key)) {
retv[key] = value;
}
}
return retv;
}
const newGlobals2015 = getDiff(globals.es2015, globals.es5); // 19 variables such as Promise, Map, ...
const newGlobals2017 = {
Atomics: false,
SharedArrayBuffer: false
};
const newGlobals2020 = {
BigInt: false,
BigInt64Array: false,
BigUint64Array: false,
globalThis: false
};
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
/** @type {Map<string, import("../lib/shared/types").Environment>} */
module.exports = new Map(Object.entries({
// Language
builtin: {
globals: globals.es5
},
es6: {
globals: newGlobals2015,
parserOptions: {
ecmaVersion: 6
}
},
es2015: {
globals: newGlobals2015,
parserOptions: {
ecmaVersion: 6
}
},
es2017: {
globals: { ...newGlobals2015, ...newGlobals2017 },
parserOptions: {
ecmaVersion: 8
}
},
es2020: {
globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },
parserOptions: {
ecmaVersion: 11
}
},
// Platforms
browser: {
globals: globals.browser
},
node: {
globals: globals.node,
parserOptions: {
ecmaFeatures: {
globalReturn: true
}
}
},
"shared-node-browser": {
globals: globals["shared-node-browser"]
},
worker: {
globals: globals.worker
},
serviceworker: {
globals: globals.serviceworker
},
// Frameworks
commonjs: {
globals: globals.commonjs,
parserOptions: {
ecmaFeatures: {
globalReturn: true
}
}
},
amd: {
globals: globals.amd
},
mocha: {
globals: globals.mocha
},
jasmine: {
globals: globals.jasmine
},
jest: {
globals: globals.jest
},
phantomjs: {
globals: globals.phantomjs
},
jquery: {
globals: globals.jquery
},
qunit: {
globals: globals.qunit
},
prototypejs: {
globals: globals.prototypejs
},
shelljs: {
globals: globals.shelljs
},
meteor: {
globals: globals.meteor
},
mongo: {
globals: globals.mongo
},
protractor: {
globals: globals.protractor
},
applescript: {
globals: globals.applescript
},
nashorn: {
globals: globals.nashorn
},
atomtest: {
globals: globals.atomtest
},
embertest: {
globals: globals.embertest
},
webextensions: {
globals: globals.webextensions
},
greasemonkey: {
globals: globals.greasemonkey
}
}));

View File

@ -0,0 +1,22 @@
{
"rules": {
"generator-star": ["generator-star-spacing"],
"global-strict": ["strict"],
"no-arrow-condition": ["no-confusing-arrow", "no-constant-condition"],
"no-comma-dangle": ["comma-dangle"],
"no-empty-class": ["no-empty-character-class"],
"no-empty-label": ["no-labels"],
"no-extra-strict": ["strict"],
"no-reserved-keys": ["quote-props"],
"no-space-before-semi": ["semi-spacing"],
"no-wrap-func": ["no-extra-parens"],
"space-after-function-name": ["space-before-function-paren"],
"space-after-keywords": ["keyword-spacing"],
"space-before-function-parentheses": ["space-before-function-paren"],
"space-before-keywords": ["keyword-spacing"],
"space-in-brackets": ["object-curly-spacing", "array-bracket-spacing", "computed-property-spacing"],
"space-return-throw-case": ["keyword-spacing"],
"space-unary-word-ops": ["space-unary-ops"],
"spaced-line-comment": ["spaced-comment"]
}
}

17
eslint/docs/README.md Normal file
View File

@ -0,0 +1,17 @@
# Documentation
Welcome to our documentation pages! What would you like to view?
## [User Guide](user-guide)
Intended for end users of ESLint. Contains information about core rules, configuration, command line options, formatters, and integrations,
as well as guides for migrating from earlier versions of ESLint.
## [Developer Guide](developer-guide)
Intended for contributors to ESLint and people who wish to extend ESLint. Contains information about contributing to ESLint; creating custom
rules, configurations, plugins, and formatters; and information about our architecture and Node.js API.
## [Maintainer Guide](maintainer-guide)
Intended for maintainers of ESLint.

View File

@ -0,0 +1,38 @@
# About
ESLint is an open source JavaScript linting utility originally created by Nicholas C. Zakas in June 2013. Code [linting][] is a type of static analysis that is frequently used to find problematic patterns or code that doesn't adhere to certain style guidelines. There are code linters for most programming languages, and compilers sometimes incorporate linting into the compilation process.
JavaScript, being a dynamic and loosely-typed language, is especially prone to developer error. Without the benefit of a compilation process, JavaScript code is typically executed in order to find syntax or other errors. Linting tools like ESLint allow developers to discover problems with their JavaScript code without executing it.
The primary reason ESLint was created was to allow developers to create their own linting rules. ESLint is designed to have all rules completely pluggable. The default rules are written just like any plugin rules would be. They can all follow the same pattern, both for the rules themselves as well as tests. While ESLint will ship with some built-in rules to make it useful from the start, you'll be able to dynamically load rules at any point in time.
ESLint is written using Node.js to provide a fast runtime environment and easy installation via [npm][].
[linting]: https://en.wikipedia.org/wiki/Lint_(software)
[npm]: https://npmjs.org/
## Philosophy
Everything is pluggable:
* Rule API is used both by bundled and custom rules
* Formatter API is used both by bundled and custom formatters
* Additional rules and formatters can be specified at runtime
* Rules and formatters don't have to be bundled to be used
Every rule:
* Is standalone
* Can be turned off or on (nothing can be deemed "too important to turn off")
* Can be set to a warning or error individually
Additionally:
* Rules are "agenda free" - ESLint does not promote any particular coding style
* Any bundled rules are generalizable
The project:
* Values documentation and clear communication
* Is as transparent as possible
* Believes in the importance of testing

View File

@ -0,0 +1,47 @@
# Developer Guide
This guide is intended for those who wish to:
* Contribute code to ESLint
* Create their own rules for ESLint
In order to work with ESLint as a developer, it's recommended that:
* You know JavaScript, since ESLint is written in JavaScript.
* You have some familiarity with Node.js, since ESLint runs on it.
* You're comfortable with command-line programs.
* You understand unit tests and why they're important.
If that sounds like you, then continue reading to get started.
## Section 1: Get the [Source Code](source-code.md)
Before you can get started, you'll need to get a copy of the ESLint source code. This section explains how to do that and a little about the source code structure.
## Section 2: Set up a [Development Environment](development-environment.md)
Developing for ESLint is a bit different than running it on the command line. This section shows you how to set up a development environment and get you ready to write code.
## Section 3: Run the [Unit Tests](unit-tests.md)
There are a lot of unit tests included with ESLint to make sure that we're keeping on top of code quality. This section explains how to run the unit tests.
## Section 4: [Working with Rules](working-with-rules.md)
You're finally ready to start working with rules. You may want to fix an existing rule or create a new one. This section explains how to do all of that.
## Section 5: [Working with Plugins](working-with-plugins.md)
You've developed library-specific rules for ESLint and you want to share it with the community. You can publish an ESLint plugin on npm.
## Section 6: [Working with Custom Parsers](working-with-custom-parsers.md)
If you aren't going to use the default parser of ESLint, this section explains about using custom parsers.
## Section 7: [Node.js API](nodejs-api.md)
If you're interested in writing a tool that uses ESLint, then you can use the Node.js API to get programmatic access to functionality.
## Section 8: [Contributing](contributing/)
Once you've made changes that you want to share with the community, the next step is to submit those changes back via a pull request.

View File

@ -0,0 +1,92 @@
# Architecture
<center><img alt="dependency graph" src="./architecture/dependency.svg"></center>
At a high level, there are a few key parts to ESLint:
* `bin/eslint.js` - this is the file that actually gets executed with the command line utility. It's a dumb wrapper that does nothing more than bootstrap ESLint, passing the command line arguments to `cli`. This is intentionally small so as not to require heavy testing.
* `lib/api.js` - this is the entry point of `require("eslint")`. This file exposes an object that contains public classes `Linter`, `CLIEngine`, `RuleTester`, and `SourceCode`.
* `lib/cli.js` - this is the heart of the ESLint CLI. It takes an array of arguments and then uses `eslint` to execute the commands. By keeping this as a separate utility, it allows others to effectively call ESLint from within another Node.js program as if it were done on the command line. The main call is `cli.execute()`. This is also the part that does all the file reading, directory traversing, input, and output.
* `lib/init/` - this module contains `--init` functionality that set up a configuration file for end users.
* `lib/cli-engine/` - this module is `CLIEngine` class that finds source code files and configuration files then does code verifying with the `Linter` class. This includes the loading logic of configuration files, parsers, plugins, and formatters.
* `lib/linter/` - this module is the core `Linter` class that does code verifying based on configuration options. This file does no file I/O and does not interact with the `console` at all. For other Node.js programs that have JavaScript text to verify, they would be able to use this interface directly.
* `lib/rule-tester/` - this module is `RuleTester` class that is a wrapper around Mocha so that rules can be unit tested. This class lets us write consistently formatted tests for each rule that is implemented and be confident that each of the rules work. The RuleTester interface was modeled after Mocha and works with Mocha's global testing methods. RuleTester can also be modified to work with other testing frameworks.
* `lib/source-code/` - this module is `SourceCode` class that is used to represent the parsed source code. It takes in source code and the Program node of the AST representing the code.
* `lib/rules/` - this contains built-in rules that verify source code.
## The `cli` object
The `cli` object is the API for the command line interface. Literally, the `bin/eslint.js` file simply passes arguments to the `cli` object and then sets `process.exitCode` to the returned exit code.
The main method is `cli.execute()`, which accepts an array of strings that represent the command line options (as if `process.argv` were passed without the first two arguments). If you want to run ESLint from inside of another program and have it act like the CLI, then `cli` is the object to use.
This object's responsibilities include:
* Interpreting command line arguments
* Reading from the file system
* Outputting to the console
* Outputting to the filesystem
* Use a formatter
* Returning the correct exit code
This object may not:
* Call `process.exit()` directly
* Perform any asynchronous operations
## The `CLIEngine` object
The `CLIEngine` type represents the core functionality of the CLI except that it reads nothing from the command line and doesn't output anything by default. Instead, it accepts many (but not all) of the arguments that are passed into the CLI. It reads both configuration and source files as well as managing the environment that is passed into the `Linter` object.
The main method of the `CLIEngine` is `executeOnFiles()`, which accepts an array of file and directory names to run the linter on.
This object's responsibilities include:
* Managing the execution environment for `Linter`
* Reading from the file system
* Reading configuration information from config files (including `.eslintrc` and `package.json`)
This object may not:
* Call `process.exit()` directly
* Perform any asynchronous operations
* Output to the console
* Use formatters
## The `Linter` object
The main method of the `Linter` object is `verify()` and accepts two arguments: the source text to verify and a configuration object (the baked configuration of the given configuration file plus command line options). The method first parses the given text with `espree` (or whatever the configured parser is) and retrieves the AST. The AST is produced with both line/column and range locations which are useful for reporting location of issues and retrieving the source text related to an AST node, respectively.
Once the AST is available, `estraverse` is used to traverse the AST from top to bottom. At each node, the `Linter` object emits an event that has the same name as the node type (i.e., "Identifier", "WithStatement", etc.). On the way back up the subtree, an event is emitted with the AST type name and suffixed with ":exit", such as "Identifier:exit" - this allows rules to take action both on the way down and on the way up in the traversal. Each event is emitted with the appropriate AST node available.
This object's responsibilities include:
* Inspecting JavaScript code strings
* Creating an AST for the code
* Executing rules on the AST
* Reporting back the results of the execution
This object may not:
* Call `process.exit()` directly
* Perform any asynchronous operations
* Use Node.js-specific features
* Access the file system
* Call `console.log()` or any other similar method
## Rules
Individual rules are the most specialized part of the ESLint architecture. Rules can do very little, they are simply a set of instructions executed against an AST that is provided. They do get some context information passed in, but the primary responsibility of a rule is to inspect the AST and report warnings.
These objects' responsibilities are:
* Inspect the AST for specific patterns
* Reporting warnings when certain patterns are found
These objects may not:
* Call `process.exit()` directly
* Perform any asynchronous operations
* Use Node.js-specific features
* Access the file system
* Call `console.log()` or any other similar method

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,925 @@
# Code Conventions
Programming language style guides are important for the long-term maintainability of software. This guide is based on the [Code Conventions for the Java Programming Language](https://java.sun.com/docs/codeconv/) and [Douglas Crockford's Code Conventions for the JavaScript Programming Language](http://javascript.crockford.com/code.html). Modifications have been made due to my personal experience and preferences.
## File Format
Each file has this same basic format:
```js
/**
* @fileoverview Description of the file
* @author Your Name
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
// require() statements
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
// private methods/data
//------------------------------------------------------------------------------
// Public Interface
//------------------------------------------------------------------------------
// exported objects/methods
module.exports = {
};
```
The `@author` field gives you credit for having created the file.
## Indentation
Each indentation level is made up of four spaces. Do not use tabs.
// Good
if (true) {
doSomething();
}
## Primitive Literals
Strings should always use double quotes (never single quotes) and should always appear on a single line. Never use a slash to create a new line in a string.
// Good
var name = "Nicholas";
// Bad: Single quotes
var name = 'Nicholas';
// Bad: Wrapping to second line
var longString = "Here's the story, of a man \
named Brady.";
Numbers should be written as decimal integers, e-notation integers, hexadecimal integers or floating-point decimals with at least one digit before and one digit after the decimal point. Never use octal literals.
// Good
var count = 10;
// Good
var price = 10.0;
var price = 10.00;
// Good
var num = 0xA2;
// Good
var num = 1e23;
// Bad: Hanging decimal point
var price = 10.;
// Bad: Leading decimal point
var price = .1;
// Bad: Octal (base 8) is deprecated
var num = 010;
The special value `null` should be used only in the following situations:
1. To initialize a variable that may later be assign an object value.
1. To compare against an initialized variable that may or may not have an object value.
1. To pass into a function where an object is expected.
1. To return from a function where an object is expected.
Examples:
// Good
var person = null;
// Good
function getPerson() {
if (condition) {
return new Person("Nicholas");
} else {
return null;
}
}
// Good
var person = getPerson();
if (person !== null){
doSomething();
}
// Bad: Testing against uninitialized variable
var person;
if (person != null){
doSomething();
}
// Bad: Testing to see if an argument was passed
function doSomething(arg1, arg2, arg3, arg4){
if (arg4 != null){
doSomethingElse();
}
}
Never use the special value `undefined`. To see if a variable has been defined, use the `typeof` operator:
// Good
if (typeof variable == "undefined") {
// do something
}
// Bad: Using undefined literal
if (variable == undefined) {
// do something
}
## Operator Spacing
Operators with two operands must be preceded and followed by a single space to make the expression clear. Operators include assignments and logical operators.
// Good
var found = (values[i] === item);
// Good
if (found && (count > 10)) {
doSomething();
}
// Good
for (i = 0; i < count; i++) {
process(i);
}
// Bad: Missing spaces
var found = (values[i]===item);
// Bad: Missing spaces
if (found&&(count>10)) {
doSomething();
}
// Bad: Missing spaces
for (i=0; i<count; i++) {
process(i);
}
## Parentheses Spacing
When parentheses are used, there should be no whitespace immediately after the opening paren or immediately before the closing paren.
// Good
var found = (values[i] === item);
// Good
if (found && (count > 10)) {
doSomething();
}
// Good
for (i = 0; i < count; i++) {
process(i);
}
// Bad: Extra space after opening paren
var found = ( values[i] === item);
// Bad: Extra space before closing paren
if (found && (count > 10) ) {
doSomething();
}
// Bad: Extra space around argument
for (i = 0; i < count; i++) {
process( i );
}
## Object Literals
Object literals should have the following format:
* The opening brace should be on the same line as the containing statement.
* Each property-value pair should be indented one level with the first property appearing on the next line after the opening brace.
* Each property-value pair should have an unquoted property name, followed by a colon (no space preceding it), followed by the value.
* If the value is a function, it should wrap under the property name and should have a blank line both before and after the function.
* Additional empty lines may be inserted to group related properties or otherwise improve readability.
* The closing brace should be on a separate line.
Examples:
// Good
var object = {
key1: value1,
key2: value2,
func: function() {
// do something
},
key3: value3
};
// Bad: Improper indentation
var object = {
key1: value1,
key2: value2
};
// Bad: Missing blank lines around function
var object = {
key1: value1,
key2: value2,
func: function() {
// do something
},
key3: value3
};
When an object literal is passed to a function, the opening brace should be on the same line as if the value is a variable. All other formatting rules from above still apply.
// Good
doSomething({
key1: value1,
key2: value2
});
// Bad: All on one line
doSomething({ key1: value1, key2: value2 });
## Comments
Make frequent use of comments to aid others in understanding your code. Use comments when:
* Code is difficult to understand.
* The code might be mistaken for an error.
* Browser-specific code is necessary but not obvious.
* Documentation generation is necessary for an object, method, or property (use appropriate documentation comments).
### Single-Line Comments
Single-line comments should be used to document one line of code or a group of related lines of code. A single-line comment may be used in three ways:
1. On a separate line, describing the code beneath it.
1. At the end of a line, describing the code before it.
1. On multiple lines, to comment out sections of code.
When on a separate line, a single-line comment should be at the same indentation level as the code it describes and be preceded by a single line. Never use multiple single-line comments on consecutive lines, use a multi-line comment instead.
// Good
if (condition){
// if you made it here, then all security checks passed
allowed();
}
// Bad: No empty line preceding comment
if (condition){
// if you made it here, then all security checks passed
allowed();
}
// Bad: Wrong indentation
if (condition){
// if you made it here, then all security checks passed
allowed();
}
// Bad: This should be a multi-line comment
// This next piece of code is quite difficult, so let me explain.
// What you want to do is determine if the condition is true
// and only then allow the user in. The condition is calculated
// from several different functions and may change during the
// lifetime of the session.
if (condition){
// if you made it here, then all security checks passed
allowed();
}
For single-line comments at the end of a line, ensure there is at least one indentation level between the end of the code and the beginning of the comment:
// Good
var result = something + somethingElse; // somethingElse will never be null
// Bad: Not enough space between code and comment
var result = something + somethingElse;// somethingElse will never be null
The only acceptable time to have multiple single-line comments on successive lines is to comment out large sections of code. Multi-line comments should not be used for this purpose.
// Good
// if (condition){
// doSomething();
// thenDoSomethingElse();
// }
### Multi-Line Comments
Multi-line comments should be used to document code that requires more explanation. Each multi-line comment should have at least three lines:
1. The first line contains only the `/*` comment opening. No further text is allowed on this line.
1. The next line(s) have a `*` aligned with the `*` in the first line. Text is allowed on these lines.
1. The last line has the `*/` comment opening aligned with the preceding lines. No other text is allowed on this line.
The first line of multi-comments should be indented to the same level as the code it describes. Each subsequent line should have the same indentation plus one space (for proper alignment of the `*` characters). Each multi-line comment should be preceded by one empty line.
// Good
if (condition){
/*
* if you made it here,
* then all security checks passed
*/
allowed();
}
// Bad: No empty line preceding comment
if (condition){
/*
* if you made it here,
* then all security checks passed
*/
allowed();
}
// Bad: Missing a space after asterisk
if (condition){
/*
*if you made it here,
*then all security checks passed
*/
allowed();
}
// Bad: Wrong indentation
if (condition){
/*
* if you made it here,
* then all security checks passed
*/
allowed();
}
// Bad: Don't use multi-line comments for trailing comments
var result = something + somethingElse; /*somethingElse will never be null*/
### Comment Annotations
Comments may be used to annotate pieces of code with additional information. These annotations take the form of a single word followed by a colon. The acceptable annotations are:
* `TODO` - indicates that the code is not yet complete. Information about the next steps should be included.
* `HACK` - indicates that the code is using a shortcut. Information about why the hack is being used should be included. This may also indicate that it would be nice to come up with a better way to solve the problem.
* `XXX` - indicates that the code is problematic and should be fixed as soon as possible.
* `FIXME` - indicates that the code is problematic and should be fixed soon. Less important than `XXX`.
* `REVIEW` - indicates that the code needs to be reviewed for potential changes.
These annotations may be used with either single-line or multi-line comments and should follow the same formatting rules as the general comment type. Examples:
// Good
// TODO: I'd like to find a way to make this faster
doSomething();
// Good
/*
* HACK: Have to do this for IE. I plan on revisiting in
* the future when I have more time. This probably should
* get replaced before v1.2.
*/
if (document.all) {
doSomething();
}
// Good
// REVIEW: Is there a better way to do this?
if (document.all) {
doSomething();
}
// Bad: Annotation spacing is incorrect
// TODO : I'd like to find a way to make this faster
doSomething();
// Bad: Comment should be at the same indentation as code
// REVIEW: Is there a better way to do this?
if (document.all) {
doSomething();
}
## Variable Declarations
All variables should be declared before they are used. Variable declarations should take place at the beginning of a function using a single `var` statement with one variable per line. All lines after the first should be indented one level so the variable names line up. Variables should be initialized when declared if applicable and the equals operator should be at a consistent indentation level. Initialized variables should come first followed by uninitialized variables.
// Good
var count = 10,
name = "Nicholas",
found = false,
empty;
// Bad: Improper initialization alignment
var count = 10,
name = "Nicholas",
found= false,
empty;
// Bad: Incorrect indentation
var count = 10,
name = "Nicholas",
found = false,
empty;
// Bad: Multiple declarations on one line
var count = 10, name = "Nicholas",
found = false, empty;
// Bad: Uninitialized variables first
var empty,
count = 10,
name = "Nicholas",
found = false;
// Bad: Multiple var statements
var count = 10,
name = "Nicholas";
var found = false,
empty;
Always declare variables. Implied globals should not be used.
## Function Declarations
Functions should be declared before they are used. When a function is not a method (not attached to an object) it should be defined using function declaration format (not function expression format nor using the `Function` constructor). There should be no space between the function name and the opening parentheses. There should be one space between the closing parentheses and the right brace. The right brace should be on the same line as the `function` keyword. There should be no space after the opening parentheses or before the closing parentheses. Named arguments should have a space after the comma but not before it. The function body should be indented one level.
// Good
function doSomething(arg1, arg2) {
return arg1 + arg2;
}
// Bad: Improper spacing of first line
function doSomething (arg1, arg2){
return arg1 + arg2;
}
// Bad: Function expression
var doSomething = function(arg1, arg2) {
return arg1 + arg2;
};
// Bad: Left brace on wrong line
function doSomething(arg1, arg2)
{
return arg1 + arg2;
}
// Bad: Using Function constructor
var doSomething = new Function("arg1", "arg2", "return arg1 + arg2");
Functions declared inside of other functions should be declared immediately after the `var` statement.
// Good
function outer() {
var count = 10,
name = "Nicholas",
found = false,
empty;
function inner() {
// code
}
// code that uses inner()
}
// Bad: Inner function declared before variables
function outer() {
function inner() {
// code
}
var count = 10,
name = "Nicholas",
found = false,
empty;
// code that uses inner()
}
Anonymous functions may be used for assignment of object methods or as arguments to other functions. There should be no space between the `function` keyword and the opening parentheses.
// Good
object.method = function() {
// code
};
// Bad: Incorrect spacing
object.method = function () {
// code
};
Immediately-invoked functions should surround the entire function call with parentheses.
// Good
var value = (function() {
// function body
return {
message: "Hi"
}
}());
// Bad: No parentheses around function call
var value = function() {
// function body
return {
message: "Hi"
}
}();
// Bad: Improper parentheses placement
var value = (function() {
// function body
return {
message: "Hi"
}
})();
## Naming
Care should be taken to name variables and functions properly. Names should be limited to alphanumeric characters and, in some cases, the underscore character. Do not use the dollar sign (`$`) or back slash (`\`) characters in any names.
Variable names should be formatted in camel case with the first letter being lowercase and the first letter of each subsequent word being uppercase. The first word of a variable name should be a noun (not a verb) to avoid confusion with functions. Do not use underscore for variable names.
// Good
var accountNumber = "8401-1";
// Bad: Begins with uppercase letter
var AccountNumber = "8401-1";
// Bad: Begins with verb
var getAccountNumber = "8401-1";
// Bad: Uses underscore
var account_number = "8401-1";
Function names should also be formatted using camel case. The first word of a function name should be a verb (not a noun) to avoid confusion with variables. Do not use underscore for function names.
// Good
function doSomething() {
// code
}
// Bad: Begins with uppercase letter
function DoSomething() {
// code
}
// Bad: Begins with noun
function car() {
// code
}
// Bad: Uses underscores
function do_something() {
// code
}
Constructor functions, those functions used with the `new` operator to create new objects, should be formatted in camel case but must begin with an uppercase letter. Constructor function names should begin with a non-verb because `new` is the action of creating an object instance.
// Good
function MyObject() {
// code
}
// Bad: Begins with lowercase letter
function myObject() {
// code
}
// Bad: Uses underscores
function My_Object() {
// code
}
// Bad: Begins with verb
function getMyObject() {
// code
}
Variables that act as constants (values that won't be changed) should be formatted using all uppercase letters with words separated by a single underscore.
// Good
var TOTAL_COUNT = 10;
// Bad: Camel case
var totalCount = 10;
// Bad: Mixed case
var total_COUNT = 10;
Object properties follow the same naming conventions as variables. Object methods follow the same naming conventions as functions. If a property or method is meant to be private, then it should be prefixed with an underscore character.
// Good
var object = {
_count: 10,
_getCount: function () {
return this._count;
}
};
## Strict Mode
Strict mode should be used in all modules, specified below the file overview comment and above everything else:
// Bad: Strict mode in functions
function doSomething() {
"use strict";
// code
}
// Bad: Strict mode in global scope and redundant strict mode directive in function
"use strict"; // This one is good
function doSomething() {
"use strict"; // This one is bad
// code
}
// Good: Global strict mode
"use strict";
function doSomething() {
// no "use strict" here
// code
}
## Assignments
When assigning a value to a variable, use parentheses around a right-side expression that contains a comparison.
// Good
var flag = (i < count);
// Bad: Missing parentheses
var flag = i < count;
## Equality Operators
Use `===` and `!==` instead of `==` and `!=`. This avoids type coercion errors.
// Good
var same = (a === b);
// Bad: Using ==
var same = (a == b);
## Ternary Operator
The ternary operator should be used only for assigning values conditionally and never as a shortcut for an `if` statement.
// Good
var value = condition ? value1 : value2;
// Bad: no assignment, should be an if statement
condition ? doSomething() : doSomethingElse();
## Statements
### Simple Statements
Each line should contain at most one statement. All simple statements should end with a semicolon (`;`).
// Good
count++;
a = b;
// Bad: Multiple statements on one line
count++; a = b;
### return Statement
A return statement with a value should not use parentheses unless they make the return value more obvious in some way. Example:
return;
return collection.size();
return (size > 0 ? size : defaultSize);
### Compound Statements
Compound statements are lists of statements enclosed inside of braces.
* The enclosed statements should be indented one more level than the compound statement.
* The opening brace should be at the end of the line that begins the compound statement; the closing brace should begin a line and be indented to the beginning of the compound statement.
* Braces are used around all statements, even single statements, when they are part of a control structure, such as a `if` or `for` statement. This makes it easier to add statements without accidentally introducing bugs due to forgetting to add braces.
* The statement beginning keyword, such as `if`, should be followed by one space and the opening brace should be preceded by a space.
### if Statement
The `if` class of statements should have the following form:
if (condition) {
statements
}
if (condition) {
statements
} else {
statements
}
if (condition) {
statements
} else if (condition) {
statements
} else {
statements
}
It is never permissible to omit the braces in any part of an `if` statement.
// Good
if (condition) {
doSomething();
}
// Bad: Improper spacing
if(condition){
doSomething();
}
// Bad: Missing braces
if (condition)
doSomething();
// Bad: All on one line
if (condition) { doSomething(); }
// Bad: All on one line without braces
if (condition) doSomething();
### for Statement
The `for` class of statements should have the following form:
for (initialization; condition; update) {
statements
}
for (variable in object) {
statements
}
Variables should not be declared in the initialization section of a `for` statement.
// Good
var i,
len;
for (i=0, len=10; i < len; i++) {
// code
}
// Bad: Variables declared during initialization
for (var i=0, len=10; i < len; i++) {
// code
}
// Bad: Variables declared during initialization
for (var prop in object) {
// code
}
When using a `for-in` statement, double-check whether or not you need to use `hasOwnProperty()` to filter out object members.
### while Statement
The `while` class of statements should have the following form:
while (condition) {
statements
}
### do Statement
The `do` class of statements should have the following form:
do {
statements
} while (condition);
Note the use of a semicolon as the final part of this statement. There should be a space before and after the `while` keyword.
### switch Statement
The `switch` class of statements should have the following form:
switch (expression) {
case expression:
statements
default:
statements
}
Each `case` is indented one level under the `switch`. Each `case` after the first, including `default`, should be preceded by a single empty line.
Each group of statements (except the default) should end with `break`, `return`, `throw`, or a comment indicating fall through.
// Good
switch (value) {
case 1:
/* falls through */
case 2:
doSomething();
break;
case 3:
return true;
default:
throw new Error("This shouldn't happen.);
}
If a `switch` doesn't have a `default` case, then it should be indicated with a comment.
// Good
switch (value) {
case 1:
/*falls through*/
case 2:
doSomething();
break;
case 3:
return true;
// no default
}
### try Statement
The `try` class of statements should have the following form:
try {
statements
} catch (variable) {
statements
}
try {
statements
} catch (variable) {
statements
} finally {
statements
}
## Whitespace
Blank lines improve readability by setting off sections of code that are logically related.
Two blank lines should always be used in the following circumstances:
* Between sections of a source file
* Between class and interface definitions
One blank line should always be used in the following circumstances:
* Between methods
* Between the local variables in a method and its first statement
* Before a multi-line or single-line comment
* Between logical sections inside a method to improve readability
Blank spaces should be used in the following circumstances:
* A keyword followed by a parenthesis should be separated by a space.
* A blank space should appear after commas in argument lists.
* All binary operators except dot (`.`) should be separated from their operands by spaces. Blank spaces should never separate unary operators such as unary minus, increment (`++`), and decrement (`--`) from their operands.
* The expressions in a `for` statement should be separated by blank spaces. Blank spaces should only be used after semicolons, not before.
## Things to Avoid
* Never use the primitive wrapper types, such as `String`, to create new objects.
* Never use `eval()`.
* Never use the `with` statement. This statement isn't available in strict mode and likely won't be available in future ECMAScript editions.

View File

@ -0,0 +1,551 @@
# Code Path Analysis Details
ESLint's rules can use code paths.
The code path is execution routes of programs.
It forks/joins at such as `if` statements.
```js
if (a && b) {
foo();
}
bar();
```
![Code Path Example](./code-path-analysis/helo.svg)
## Objects
Program is expressed with several code paths.
A code path is expressed with objects of two kinds: `CodePath` and `CodePathSegment`.
### `CodePath`
`CodePath` expresses whole of one code path.
This object exists for each function and the global.
This has references of both the initial segment and the final segments of a code path.
`CodePath` has the following properties:
* `id` (`string`) - A unique string. Respective rules can use `id` to save additional information for each code path.
* `initialSegment` (`CodePathSegment`) - The initial segment of this code path.
* `finalSegments` (`CodePathSegment[]`) - The final segments which includes both returned and thrown.
* `returnedSegments` (`CodePathSegment[]`) - The final segments which includes only returned.
* `thrownSegments` (`CodePathSegment[]`) - The final segments which includes only thrown.
* `currentSegments` (`CodePathSegment[]`) - Segments of the current position.
* `upper` (`CodePath|null`) - The code path of the upper function/global scope.
* `childCodePaths` (`CodePath[]`) - Code paths of functions this code path contains.
### `CodePathSegment`
`CodePathSegment` is a part of a code path.
A code path is expressed with plural `CodePathSegment` objects, it's similar to doubly linked list.
Difference from doubly linked list is what there are forking and merging (the next/prev are plural).
`CodePathSegment` has the following properties:
* `id` (`string`) - A unique string. Respective rules can use `id` to save additional information for each segment.
* `nextSegments` (`CodePathSegment[]`) - The next segments. If forking, there are two or more. If final, there is nothing.
* `prevSegments` (`CodePathSegment[]`) - The previous segments. If merging, there are two or more. If initial, there is nothing.
* `reachable` (`boolean`) - A flag which shows whether or not it's reachable. This becomes `false` when preceded by `return`, `throw`, `break`, or `continue`.
## Events
There are five events related to code paths, and you can define event handlers in rules.
```js
module.exports = function(context) {
return {
/**
* This is called at the start of analyzing a code path.
* In this time, the code path object has only the initial segment.
*
* @param {CodePath} codePath - The new code path.
* @param {ASTNode} node - The current node.
* @returns {void}
*/
"onCodePathStart": function(codePath, node) {
// do something with codePath
},
/**
* This is called at the end of analyzing a code path.
* In this time, the code path object is complete.
*
* @param {CodePath} codePath - The completed code path.
* @param {ASTNode} node - The current node.
* @returns {void}
*/
"onCodePathEnd": function(codePath, node) {
// do something with codePath
},
/**
* This is called when a code path segment was created.
* It meant the code path is forked or merged.
* In this time, the segment has the previous segments and has been
* judged reachable or not.
*
* @param {CodePathSegment} segment - The new code path segment.
* @param {ASTNode} node - The current node.
* @returns {void}
*/
"onCodePathSegmentStart": function(segment, node) {
// do something with segment
},
/**
* This is called when a code path segment was leaved.
* In this time, the segment does not have the next segments yet.
*
* @param {CodePathSegment} segment - The leaved code path segment.
* @param {ASTNode} node - The current node.
* @returns {void}
*/
"onCodePathSegmentEnd": function(segment, node) {
// do something with segment
},
/**
* This is called when a code path segment was looped.
* Usually segments have each previous segments when created,
* but when looped, a segment is added as a new previous segment into a
* existing segment.
*
* @param {CodePathSegment} fromSegment - A code path segment of source.
* @param {CodePathSegment} toSegment - A code path segment of destination.
* @param {ASTNode} node - The current node.
* @returns {void}
*/
"onCodePathSegmentLoop": function(fromSegment, toSegment, node) {
// do something with segment
}
};
};
```
### About `onCodePathSegmentLoop`
This event is always fired when the next segment has existed already.
That timing is the end of loops mainly.
For Example 1:
```js
while (a) {
a = foo();
}
bar();
```
1. First, the analysis advances to the end of loop.
![Loop Event's Example 1](./code-path-analysis/loop-event-example-while-1.svg)
2. Second, it creates the looping path.
At this time, the next segment has existed already, so the `onCodePathSegmentStart` event is not fired.
It fires `onCodePathSegmentLoop` instead.
![Loop Event's Example 2](./code-path-analysis/loop-event-example-while-2.svg)
3. Last, it advances to the end.
![Loop Event's Example 3](./code-path-analysis/loop-event-example-while-3.svg)
For example 2:
```js
for (let i = 0; i < 10; ++i) {
foo(i);
}
bar();
```
1. `for` statements are more complex.
First, the analysis advances to `ForStatement.update`.
The `update` segment is hovered at first.
![Loop Event's Example 1](./code-path-analysis/loop-event-example-for-1.svg)
2. Second, it advances to `ForStatement.body`.
Of course the `body` segment is preceded by the `test` segment.
It keeps the `update` segment hovering.
![Loop Event's Example 2](./code-path-analysis/loop-event-example-for-2.svg)
3. Third, it creates the looping path from `body` segment to `update` segment.
At this time, the next segment has existed already, so the `onCodePathSegmentStart` event is not fired.
It fires `onCodePathSegmentLoop` instead.
![Loop Event's Example 3](./code-path-analysis/loop-event-example-for-3.svg)
4. Fourth, also it creates the looping path from `update` segment to `test` segment.
At this time, the next segment has existed already, so the `onCodePathSegmentStart` event is not fired.
It fires `onCodePathSegmentLoop` instead.
![Loop Event's Example 4](./code-path-analysis/loop-event-example-for-4.svg)
5. Last, it advances to the end.
![Loop Event's Example 5](./code-path-analysis/loop-event-example-for-5.svg)
## Usage Examples
### To check whether or not this is reachable
```js
var last = require("lodash").last;
function isReachable(segment) {
return segment.reachable;
}
module.exports = function(context) {
var codePathStack = [];
return {
// Stores CodePath objects.
"onCodePathStart": function(codePath) {
codePathStack.push(codePath);
},
"onCodePathEnd": function(codePath) {
codePathStack.pop();
},
// Checks reachable or not.
"ExpressionStatement": function(node) {
var codePath = last(codePathStack);
// Checks the current code path segments.
if (!codePath.currentSegments.some(isReachable)) {
context.report({message: "Unreachable!", node: node});
}
}
};
};
```
See Also:
[no-unreachable](https://github.com/eslint/eslint/blob/master/lib/rules/no-unreachable.js),
[no-fallthrough](https://github.com/eslint/eslint/blob/master/lib/rules/no-fallthrough.js),
[consistent-return](https://github.com/eslint/eslint/blob/master/lib/rules/consistent-return.js)
### To check state of a code path
This example is checking whether or not the parameter `cb` is called in every path.
Instances of `CodePath` and `CodePathSegment` are shared to every rule.
So a rule must not modify those instances.
Please use a map of information instead.
```js
var last = require("lodash").last;
function hasCb(node, context) {
if (node.type.indexOf("Function") !== -1) {
return context.getDeclaredVariables(node).some(function(v) {
return v.type === "Parameter" && v.name === "cb";
});
}
return false;
}
function isCbCalled(info) {
return info.cbCalled;
}
module.exports = function(context) {
var funcInfoStack = [];
var segmentInfoMap = Object.create(null);
return {
// Checks `cb`.
"onCodePathStart": function(codePath, node) {
funcInfoStack.push({
codePath: codePath,
hasCb: hasCb(node, context)
});
},
"onCodePathEnd": function(codePath, node) {
funcInfoStack.pop();
// Checks `cb` was called in every paths.
var cbCalled = codePath.finalSegments.every(function(segment) {
var info = segmentInfoMap[segment.id];
return info.cbCalled;
});
if (!cbCalled) {
context.report({
message: "`cb` should be called in every path.",
node: node
});
}
},
// Manages state of code paths.
"onCodePathSegmentStart": function(segment) {
// Ignores if `cb` doesn't exist.
if (!last(funcInfoStack).hasCb) {
return;
}
// Initialize state of this path.
var info = segmentInfoMap[segment.id] = {
cbCalled: false
};
// If there are the previous paths, merges state.
// Checks `cb` was called in every previous path.
if (segment.prevSegments.length > 0) {
info.cbCalled = segment.prevSegments.every(isCbCalled);
}
},
// Checks reachable or not.
"CallExpression": function(node) {
var funcInfo = last(funcInfoStack);
// Ignores if `cb` doesn't exist.
if (!funcInfo.hasCb) {
return;
}
// Sets marks that `cb` was called.
var callee = node.callee;
if (callee.type === "Identifier" && callee.name === "cb") {
funcInfo.codePath.currentSegments.forEach(function(segment) {
var info = segmentInfoMap[segment.id];
info.cbCalled = true;
});
}
}
};
};
```
See Also:
[constructor-super](https://github.com/eslint/eslint/blob/master/lib/rules/constructor-super.js),
[no-this-before-super](https://github.com/eslint/eslint/blob/master/lib/rules/no-this-before-super.js)
## Code Path Examples
### Hello World
```js
console.log("Hello world!");
```
![Hello World](./code-path-analysis/example-hello-world.svg)
### `IfStatement`
```js
if (a) {
foo();
} else {
bar();
}
```
![`IfStatement`](./code-path-analysis/example-ifstatement.svg)
### `IfStatement` (chain)
```js
if (a) {
foo();
} else if (b) {
bar();
} else if (c) {
hoge();
}
```
![`IfStatement` (chain)](./code-path-analysis/example-ifstatement-chain.svg)
### `SwitchStatement`
```js
switch (a) {
case 0:
foo();
break;
case 1:
case 2:
bar();
// fallthrough
case 3:
hoge();
break;
}
```
![`SwitchStatement`](./code-path-analysis/example-switchstatement.svg)
### `SwitchStatement` (has `default`)
```js
switch (a) {
case 0:
foo();
break;
case 1:
case 2:
bar();
// fallthrough
case 3:
hoge();
break;
default:
fuga();
break;
}
```
![`SwitchStatement` (has `default`)](./code-path-analysis/example-switchstatement-has-default.svg)
### `TryStatement` (try-catch)
```js
try {
foo();
if (a) {
throw new Error();
}
bar();
} catch (err) {
hoge(err);
}
last();
```
It creates the paths from `try` block to `catch` block at:
* `throw` statements.
* The first throwable node (e.g. a function call) in the `try` block.
* The end of the `try` block.
![`TryStatement` (try-catch)](./code-path-analysis/example-trystatement-try-catch.svg)
### `TryStatement` (try-finally)
```js
try {
foo();
bar();
} finally {
fuga();
}
last();
```
If there is not `catch` block, `finally` block has two current segments.
At this time, `CodePath.currentSegments.length` is `2`.
One is the normal path, and another is the leaving path (`throw` or `return`).
![`TryStatement` (try-finally)](./code-path-analysis/example-trystatement-try-finally.svg)
### `TryStatement` (try-catch-finally)
```js
try {
foo();
bar();
} catch (err) {
hoge(err);
} finally {
fuga();
}
last();
```
![`TryStatement` (try-catch-finally)](./code-path-analysis/example-trystatement-try-catch-finally.svg)
### `WhileStatement`
```js
while (a) {
foo();
if (b) {
continue;
}
bar();
}
```
![`WhileStatement`](./code-path-analysis/example-whilestatement.svg)
### `DoWhileStatement`
```js
do {
foo();
bar();
} while (a);
```
![`DoWhileStatement`](./code-path-analysis/example-dowhilestatement.svg)
### `ForStatement`
```js
for (let i = 0; i < 10; ++i) {
foo();
if (b) {
break;
}
bar();
}
```
![`ForStatement`](./code-path-analysis/example-forstatement.svg)
### `ForStatement` (for ever)
```js
for (;;) {
foo();
}
bar();
```
![`ForStatement` (for ever)](./code-path-analysis/example-forstatement-for-ever.svg)
### `ForInStatement`
```js
for (let key in obj) {
foo(key);
}
```
![`ForInStatement`](./code-path-analysis/example-forinstatement.svg)
### When there is a function
```js
function foo(a) {
if (a) {
return;
}
bar();
}
foo(false);
```
It creates two code paths.
* The global's
![When there is a function](./code-path-analysis/example-when-there-is-a-function-g.svg)
* The function's
![When there is a function](./code-path-analysis/example-when-there-is-a-function-f.svg)

View File

@ -0,0 +1,551 @@
# Code Path Analysis Details
ESLint's rules can use code paths.
The code path is execution routes of programs.
It forks/joins at such as `if` statements.
```js
if (a && b) {
foo();
}
bar();
```
![Code Path Example](./helo.svg)
## Objects
Program is expressed with several code paths.
A code path is expressed with objects of two kinds: `CodePath` and `CodePathSegment`.
### `CodePath`
`CodePath` expresses whole of one code path.
This object exists for each function and the global.
This has references of both the initial segment and the final segments of a code path.
`CodePath` has the following properties:
* `id` (`string`) - A unique string. Respective rules can use `id` to save additional information for each code path.
* `initialSegment` (`CodePathSegment`) - The initial segment of this code path.
* `finalSegments` (`CodePathSegment[]`) - The final segments which includes both returned and thrown.
* `returnedSegments` (`CodePathSegment[]`) - The final segments which includes only returned.
* `thrownSegments` (`CodePathSegment[]`) - The final segments which includes only thrown.
* `currentSegments` (`CodePathSegment[]`) - Segments of the current position.
* `upper` (`CodePath|null`) - The code path of the upper function/global scope.
* `childCodePaths` (`CodePath[]`) - Code paths of functions this code path contains.
### `CodePathSegment`
`CodePathSegment` is a part of a code path.
A code path is expressed with plural `CodePathSegment` objects, it's similar to doubly linked list.
Difference from doubly linked list is what there are forking and merging (the next/prev are plural).
`CodePathSegment` has the following properties:
* `id` (`string`) - A unique string. Respective rules can use `id` to save additional information for each segment.
* `nextSegments` (`CodePathSegment[]`) - The next segments. If forking, there are two or more. If final, there is nothing.
* `prevSegments` (`CodePathSegment[]`) - The previous segments. If merging, there are two or more. If initial, there is nothing.
* `reachable` (`boolean`) - A flag which shows whether or not it's reachable. This becomes `false` when preceded by `return`, `throw`, `break`, or `continue`.
## Events
There are five events related to code paths, and you can define event handlers in rules.
```js
module.exports = function(context) {
return {
/**
* This is called at the start of analyzing a code path.
* In this time, the code path object has only the initial segment.
*
* @param {CodePath} codePath - The new code path.
* @param {ASTNode} node - The current node.
* @returns {void}
*/
"onCodePathStart": function(codePath, node) {
// do something with codePath
},
/**
* This is called at the end of analyzing a code path.
* In this time, the code path object is complete.
*
* @param {CodePath} codePath - The completed code path.
* @param {ASTNode} node - The current node.
* @returns {void}
*/
"onCodePathEnd": function(codePath, node) {
// do something with codePath
},
/**
* This is called when a code path segment was created.
* It meant the code path is forked or merged.
* In this time, the segment has the previous segments and has been
* judged reachable or not.
*
* @param {CodePathSegment} segment - The new code path segment.
* @param {ASTNode} node - The current node.
* @returns {void}
*/
"onCodePathSegmentStart": function(segment, node) {
// do something with segment
},
/**
* This is called when a code path segment was leaved.
* In this time, the segment does not have the next segments yet.
*
* @param {CodePathSegment} segment - The leaved code path segment.
* @param {ASTNode} node - The current node.
* @returns {void}
*/
"onCodePathSegmentEnd": function(segment, node) {
// do something with segment
},
/**
* This is called when a code path segment was looped.
* Usually segments have each previous segments when created,
* but when looped, a segment is added as a new previous segment into a
* existing segment.
*
* @param {CodePathSegment} fromSegment - A code path segment of source.
* @param {CodePathSegment} toSegment - A code path segment of destination.
* @param {ASTNode} node - The current node.
* @returns {void}
*/
"onCodePathSegmentLoop": function(fromSegment, toSegment, node) {
// do something with segment
}
};
};
```
### About `onCodePathSegmentLoop`
This event is always fired when the next segment has existed already.
That timing is the end of loops mainly.
For Example 1:
```js
while (a) {
a = foo();
}
bar();
```
1. First, the analysis advances to the end of loop.
![Loop Event's Example 1](./loop-event-example-while-1.svg)
2. Second, it creates the looping path.
At this time, the next segment has existed already, so the `onCodePathSegmentStart` event is not fired.
It fires `onCodePathSegmentLoop` instead.
![Loop Event's Example 2](./loop-event-example-while-2.svg)
3. Last, it advances to the end.
![Loop Event's Example 3](./loop-event-example-while-3.svg)
For example 2:
```js
for (let i = 0; i < 10; ++i) {
foo(i);
}
bar();
```
1. `for` statements are more complex.
First, the analysis advances to `ForStatement.update`.
The `update` segment is hovered at first.
![Loop Event's Example 1](./loop-event-example-for-1.svg)
2. Second, it advances to `ForStatement.body`.
Of course the `body` segment is preceded by the `test` segment.
It keeps the `update` segment hovering.
![Loop Event's Example 2](./loop-event-example-for-2.svg)
3. Third, it creates the looping path from `body` segment to `update` segment.
At this time, the next segment has existed already, so the `onCodePathSegmentStart` event is not fired.
It fires `onCodePathSegmentLoop` instead.
![Loop Event's Example 3](./loop-event-example-for-3.svg)
4. Fourth, also it creates the looping path from `update` segment to `test` segment.
At this time, the next segment has existed already, so the `onCodePathSegmentStart` event is not fired.
It fires `onCodePathSegmentLoop` instead.
![Loop Event's Example 4](./loop-event-example-for-4.svg)
5. Last, it advances to the end.
![Loop Event's Example 5](./loop-event-example-for-5.svg)
## Usage Examples
### To check whether or not this is reachable
```js
var last = require("lodash").last;
function isReachable(segment) {
return segment.reachable;
}
module.exports = function(context) {
var codePathStack = [];
return {
// Stores CodePath objects.
"onCodePathStart": function(codePath) {
codePathStack.push(codePath);
},
"onCodePathEnd": function(codePath) {
codePathStack.pop();
},
// Checks reachable or not.
"ExpressionStatement": function(node) {
var codePath = last(codePathStack);
// Checks the current code path segments.
if (!codePath.currentSegments.some(isReachable)) {
context.report({message: "Unreachable!", node: node});
}
}
};
};
```
See Also:
[no-unreachable](https://github.com/eslint/eslint/blob/master/lib/rules/no-unreachable.js),
[no-fallthrough](https://github.com/eslint/eslint/blob/master/lib/rules/no-fallthrough.js),
[consistent-return](https://github.com/eslint/eslint/blob/master/lib/rules/consistent-return.js)
### To check state of a code path
This example is checking whether or not the parameter `cb` is called in every path.
Instances of `CodePath` and `CodePathSegment` are shared to every rule.
So a rule must not modify those instances.
Please use a map of information instead.
```js
var last = require("lodash").last;
function hasCb(node, context) {
if (node.type.indexOf("Function") !== -1) {
return context.getDeclaredVariables(node).some(function(v) {
return v.type === "Parameter" && v.name === "cb";
});
}
return false;
}
function isCbCalled(info) {
return info.cbCalled;
}
module.exports = function(context) {
var funcInfoStack = [];
var segmentInfoMap = Object.create(null);
return {
// Checks `cb`.
"onCodePathStart": function(codePath, node) {
funcInfoStack.push({
codePath: codePath,
hasCb: hasCb(node, context)
});
},
"onCodePathEnd": function(codePath, node) {
funcInfoStack.pop();
// Checks `cb` was called in every paths.
var cbCalled = codePath.finalSegments.every(function(segment) {
var info = segmentInfoMap[segment.id];
return info.cbCalled;
});
if (!cbCalled) {
context.report({
message: "`cb` should be called in every path.",
node: node
});
}
},
// Manages state of code paths.
"onCodePathSegmentStart": function(segment) {
// Ignores if `cb` doesn't exist.
if (!last(funcInfoStack).hasCb) {
return;
}
// Initialize state of this path.
var info = segmentInfoMap[segment.id] = {
cbCalled: false
};
// If there are the previous paths, merges state.
// Checks `cb` was called in every previous path.
if (segment.prevSegments.length > 0) {
info.cbCalled = segment.prevSegments.every(isCbCalled);
}
},
// Checks reachable or not.
"CallExpression": function(node) {
var funcInfo = last(funcInfoStack);
// Ignores if `cb` doesn't exist.
if (!funcInfo.hasCb) {
return;
}
// Sets marks that `cb` was called.
var callee = node.callee;
if (callee.type === "Identifier" && callee.name === "cb") {
funcInfo.codePath.currentSegments.forEach(function(segment) {
var info = segmentInfoMap[segment.id];
info.cbCalled = true;
});
}
}
};
};
```
See Also:
[constructor-super](https://github.com/eslint/eslint/blob/master/lib/rules/constructor-super.js),
[no-this-before-super](https://github.com/eslint/eslint/blob/master/lib/rules/no-this-before-super.js)
## Code Path Examples
### Hello World
```js
console.log("Hello world!");
```
![Hello World](./example-hello-world.svg)
### `IfStatement`
```js
if (a) {
foo();
} else {
bar();
}
```
![`IfStatement`](./example-ifstatement.svg)
### `IfStatement` (chain)
```js
if (a) {
foo();
} else if (b) {
bar();
} else if (c) {
hoge();
}
```
![`IfStatement` (chain)](./example-ifstatement-chain.svg)
### `SwitchStatement`
```js
switch (a) {
case 0:
foo();
break;
case 1:
case 2:
bar();
// fallthrough
case 3:
hoge();
break;
}
```
![`SwitchStatement`](./example-switchstatement.svg)
### `SwitchStatement` (has `default`)
```js
switch (a) {
case 0:
foo();
break;
case 1:
case 2:
bar();
// fallthrough
case 3:
hoge();
break;
default:
fuga();
break;
}
```
![`SwitchStatement` (has `default`)](./example-switchstatement-has-default.svg)
### `TryStatement` (try-catch)
```js
try {
foo();
if (a) {
throw new Error();
}
bar();
} catch (err) {
hoge(err);
}
last();
```
It creates the paths from `try` block to `catch` block at:
* `throw` statements.
* The first throwable node (e.g. a function call) in the `try` block.
* The end of the `try` block.
![`TryStatement` (try-catch)](./example-trystatement-try-catch.svg)
### `TryStatement` (try-finally)
```js
try {
foo();
bar();
} finally {
fuga();
}
last();
```
If there is not `catch` block, `finally` block has two current segments.
At this time, `CodePath.currentSegments.length` is `2`.
One is the normal path, and another is the leaving path (`throw` or `return`).
![`TryStatement` (try-finally)](./example-trystatement-try-finally.svg)
### `TryStatement` (try-catch-finally)
```js
try {
foo();
bar();
} catch (err) {
hoge(err);
} finally {
fuga();
}
last();
```
![`TryStatement` (try-catch-finally)](./example-trystatement-try-catch-finally.svg)
### `WhileStatement`
```js
while (a) {
foo();
if (b) {
continue;
}
bar();
}
```
![`WhileStatement`](./example-whilestatement.svg)
### `DoWhileStatement`
```js
do {
foo();
bar();
} while (a);
```
![`DoWhileStatement`](./example-dowhilestatement.svg)
### `ForStatement`
```js
for (let i = 0; i < 10; ++i) {
foo();
if (b) {
break;
}
bar();
}
```
![`ForStatement`](./example-forstatement.svg)
### `ForStatement` (for ever)
```js
for (;;) {
foo();
}
bar();
```
![`ForStatement` (for ever)](./example-forstatement-for-ever.svg)
### `ForInStatement`
```js
for (let key in obj) {
foo(key);
}
```
![`ForInStatement`](./example-forinstatement.svg)
### When there is a function
```js
function foo(a) {
if (a) {
return;
}
bar();
}
foo(false);
```
It creates two code paths.
* The global's
![When there is a function](./example-when-there-is-a-function-g.svg)
* The function's
![When there is a function](./example-when-there-is-a-function-f.svg)

View File

@ -0,0 +1,100 @@
<?xml version="1.0"?>
<svg width="167pt" height="422pt" viewBox="0.00 0.00 167.00 422.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 418)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="74" cy="-405" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="123.479,-359.602 24.5211,-359.602 12.5211,-347.602 12.5211,-330.398 24.5211,-318.398 123.479,-318.398 135.479,-330.398 135.479,-347.602 123.479,-359.602"></polygon>
<path fill="white" stroke="white" d="M24.5211,-359.602C18.5211,-359.602 12.5211,-353.602 12.5211,-347.602"></path>
<path fill="white" stroke="white" d="M12.5211,-330.398C12.5211,-324.398 18.5211,-318.398 24.5211,-318.398"></path>
<path fill="white" stroke="white" d="M123.479,-318.398C129.479,-318.398 135.479,-324.398 135.479,-330.398"></path>
<path fill="white" stroke="white" d="M135.479,-347.602C135.479,-353.602 129.479,-359.602 123.479,-359.602"></path>
<polyline fill="none" stroke="black" points="123.479,-359.602 24.5211,-359.602 "></polyline>
<path fill="none" stroke="black" d="M24.5211,-359.602C18.5211,-359.602 12.5211,-353.602 12.5211,-347.602"></path>
<polyline fill="none" stroke="black" points="12.5211,-347.602 12.5211,-330.398 "></polyline>
<path fill="none" stroke="black" d="M12.5211,-330.398C12.5211,-324.398 18.5211,-318.398 24.5211,-318.398"></path>
<polyline fill="none" stroke="black" points="24.5211,-318.398 123.479,-318.398 "></polyline>
<path fill="none" stroke="black" d="M123.479,-318.398C129.479,-318.398 135.479,-324.398 135.479,-330.398"></path>
<polyline fill="none" stroke="black" points="135.479,-330.398 135.479,-347.602 "></polyline>
<path fill="none" stroke="black" d="M135.479,-347.602C135.479,-353.602 129.479,-359.602 123.479,-359.602"></path>
<text text-anchor="middle" x="74" y="-343.2" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="74" y="-326.4" font-family="Times,serif" font-size="14.00">DoWhileStatement</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M74,-395.894C74,-389.274 74,-379.485 74,-369.94"></path>
<polygon fill="black" stroke="black" points="77.5001,-369.842 74,-359.842 70.5001,-369.842 77.5001,-369.842"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="74" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="74" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="129.147,-282.401 18.8526,-282.401 6.85263,-270.401 6.85263,-151.599 18.8526,-139.599 129.147,-139.599 141.147,-151.599 141.147,-270.401 129.147,-282.401"></polygon>
<path fill="white" stroke="white" d="M18.8526,-282.401C12.8526,-282.401 6.85263,-276.401 6.85263,-270.401"></path>
<path fill="white" stroke="white" d="M6.85263,-151.599C6.85263,-145.599 12.8526,-139.599 18.8526,-139.599"></path>
<path fill="white" stroke="white" d="M129.147,-139.599C135.147,-139.599 141.147,-145.599 141.147,-151.599"></path>
<path fill="white" stroke="white" d="M141.147,-270.401C141.147,-276.401 135.147,-282.401 129.147,-282.401"></path>
<polyline fill="none" stroke="black" points="129.147,-282.401 18.8526,-282.401 "></polyline>
<path fill="none" stroke="black" d="M18.8526,-282.401C12.8526,-282.401 6.85263,-276.401 6.85263,-270.401"></path>
<polyline fill="none" stroke="black" points="6.85263,-270.401 6.85263,-151.599 "></polyline>
<path fill="none" stroke="black" d="M6.85263,-151.599C6.85263,-145.599 12.8526,-139.599 18.8526,-139.599"></path>
<polyline fill="none" stroke="black" points="18.8526,-139.599 129.147,-139.599 "></polyline>
<path fill="none" stroke="black" d="M129.147,-139.599C135.147,-139.599 141.147,-145.599 141.147,-151.599"></path>
<polyline fill="none" stroke="black" points="141.147,-151.599 141.147,-270.401 "></polyline>
<path fill="none" stroke="black" d="M141.147,-270.401C141.147,-276.401 135.147,-282.401 129.147,-282.401"></path>
<text text-anchor="middle" x="74" y="-265.6" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="74" y="-248.8" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="74" y="-232" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="74" y="-215.2" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="74" y="-198.4" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="74" y="-181.6" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="74" y="-164.8" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
<text text-anchor="middle" x="74" y="-148" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M74,-318.313C74,-310.915 74,-301.974 74,-292.455"></path>
<polygon fill="black" stroke="black" points="77.5001,-292.368 74,-282.368 70.5001,-292.368 77.5001,-292.368"></polygon>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_2</title>
<path fill="none" stroke="black" d="M141.337,-232.995C151.84,-229.707 159,-222.375 159,-211 159,-203.357 155.768,-197.54 150.461,-193.548"></path>
<polygon fill="black" stroke="black" points="151.849,-190.329 141.337,-189.005 148.729,-196.596 151.849,-190.329"></polygon>
</g>
<g id="node5" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="136.144,-103.602 11.8558,-103.602 -0.144212,-91.6019 -0.144212,-74.3981 11.8558,-62.3981 136.144,-62.3981 148.144,-74.3981 148.144,-91.6019 136.144,-103.602"></polygon>
<path fill="white" stroke="white" d="M11.8558,-103.602C5.85579,-103.602 -0.144212,-97.6019 -0.144212,-91.6019"></path>
<path fill="white" stroke="white" d="M-0.144212,-74.3981C-0.144212,-68.3981 5.85579,-62.3981 11.8558,-62.3981"></path>
<path fill="white" stroke="white" d="M136.144,-62.3981C142.144,-62.3981 148.144,-68.3981 148.144,-74.3981"></path>
<path fill="white" stroke="white" d="M148.144,-91.6019C148.144,-97.6019 142.144,-103.602 136.144,-103.602"></path>
<polyline fill="none" stroke="black" points="136.144,-103.602 11.8558,-103.602 "></polyline>
<path fill="none" stroke="black" d="M11.8558,-103.602C5.85579,-103.602 -0.144212,-97.6019 -0.144212,-91.6019"></path>
<polyline fill="none" stroke="black" points="-0.144212,-91.6019 -0.144212,-74.3981 "></polyline>
<path fill="none" stroke="black" d="M-0.144212,-74.3981C-0.144212,-68.3981 5.85579,-62.3981 11.8558,-62.3981"></path>
<polyline fill="none" stroke="black" points="11.8558,-62.3981 136.144,-62.3981 "></polyline>
<path fill="none" stroke="black" d="M136.144,-62.3981C142.144,-62.3981 148.144,-68.3981 148.144,-74.3981"></path>
<polyline fill="none" stroke="black" points="148.144,-74.3981 148.144,-91.6019 "></polyline>
<path fill="none" stroke="black" d="M148.144,-91.6019C148.144,-97.6019 142.144,-103.602 136.144,-103.602"></path>
<text text-anchor="middle" x="74" y="-87.2" font-family="Times,serif" font-size="14.00">DoWhileStatement:exit</text>
<text text-anchor="middle" x="74" y="-70.4" font-family="Times,serif" font-size="14.00">Program:exit</text>
</g>
<g id="edge5" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M74,-139.632C74,-130.564 74,-121.701 74,-113.811"></path>
<polygon fill="black" stroke="black" points="77.5001,-113.726 74,-103.726 70.5001,-113.726 77.5001,-113.726"></polygon>
</g>
<g id="edge6" class="edge"><title>s1_3-&gt;final</title>
<path fill="none" stroke="black" d="M74,-62.3316C74,-54.2587 74,-44.8663 74,-36.5198"></path>
<polygon fill="black" stroke="black" points="77.5001,-36.3487 74,-26.3488 70.5001,-36.3488 77.5001,-36.3487"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -0,0 +1,148 @@
<?xml version="1.0"?>
<svg width="185pt" height="538pt" viewBox="0.00 0.00 185.00 538.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 534)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="114" cy="-521" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="153.319,-475.602 74.6808,-475.602 62.6808,-463.602 62.6808,-446.398 74.6808,-434.398 153.319,-434.398 165.319,-446.398 165.319,-463.602 153.319,-475.602"></polygon>
<path fill="white" stroke="white" d="M74.6808,-475.602C68.6808,-475.602 62.6808,-469.602 62.6808,-463.602"></path>
<path fill="white" stroke="white" d="M62.6808,-446.398C62.6808,-440.398 68.6808,-434.398 74.6808,-434.398"></path>
<path fill="white" stroke="white" d="M153.319,-434.398C159.319,-434.398 165.319,-440.398 165.319,-446.398"></path>
<path fill="white" stroke="white" d="M165.319,-463.602C165.319,-469.602 159.319,-475.602 153.319,-475.602"></path>
<polyline fill="none" stroke="black" points="153.319,-475.602 74.6808,-475.602 "></polyline>
<path fill="none" stroke="black" d="M74.6808,-475.602C68.6808,-475.602 62.6808,-469.602 62.6808,-463.602"></path>
<polyline fill="none" stroke="black" points="62.6808,-463.602 62.6808,-446.398 "></polyline>
<path fill="none" stroke="black" d="M62.6808,-446.398C62.6808,-440.398 68.6808,-434.398 74.6808,-434.398"></path>
<polyline fill="none" stroke="black" points="74.6808,-434.398 153.319,-434.398 "></polyline>
<path fill="none" stroke="black" d="M153.319,-434.398C159.319,-434.398 165.319,-440.398 165.319,-446.398"></path>
<polyline fill="none" stroke="black" points="165.319,-446.398 165.319,-463.602 "></polyline>
<path fill="none" stroke="black" d="M165.319,-463.602C165.319,-469.602 159.319,-475.602 153.319,-475.602"></path>
<text text-anchor="middle" x="114" y="-459.2" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="114" y="-442.4" font-family="Times,serif" font-size="14.00">ForInStatement</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M114,-511.894C114,-505.274 114,-495.485 114,-485.94"></path>
<polygon fill="black" stroke="black" points="117.5,-485.842 114,-475.842 110.5,-485.842 117.5,-485.842"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="114" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="114" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="151.097,-398 76.9034,-398 64.9034,-386 64.9034,-374 76.9034,-362 151.097,-362 163.097,-374 163.097,-386 151.097,-398"></polygon>
<path fill="white" stroke="white" d="M76.9034,-398C70.9034,-398 64.9034,-392 64.9034,-386"></path>
<path fill="white" stroke="white" d="M64.9034,-374C64.9034,-368 70.9034,-362 76.9034,-362"></path>
<path fill="white" stroke="white" d="M151.097,-362C157.097,-362 163.097,-368 163.097,-374"></path>
<path fill="white" stroke="white" d="M163.097,-386C163.097,-392 157.097,-398 151.097,-398"></path>
<polyline fill="none" stroke="black" points="151.097,-398 76.9034,-398 "></polyline>
<path fill="none" stroke="black" d="M76.9034,-398C70.9034,-398 64.9034,-392 64.9034,-386"></path>
<polyline fill="none" stroke="black" points="64.9034,-386 64.9034,-374 "></polyline>
<path fill="none" stroke="black" d="M64.9034,-374C64.9034,-368 70.9034,-362 76.9034,-362"></path>
<polyline fill="none" stroke="black" points="76.9034,-362 151.097,-362 "></polyline>
<path fill="none" stroke="black" d="M151.097,-362C157.097,-362 163.097,-368 163.097,-374"></path>
<polyline fill="none" stroke="black" points="163.097,-374 163.097,-386 "></polyline>
<path fill="none" stroke="black" d="M163.097,-386C163.097,-392 157.097,-398 151.097,-398"></path>
<text text-anchor="middle" x="114" y="-375.8" font-family="Times,serif" font-size="14.00">Identifier (obj)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_3</title>
<path fill="none" stroke="black" d="M114,-434.052C114,-426.216 114,-417.089 114,-408.636"></path>
<polygon fill="black" stroke="black" points="117.5,-408.439 114,-398.439 110.5,-408.439 117.5,-408.439"></polygon>
</g>
<g id="node5" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="119.617,-326.401 14.3833,-326.401 2.38328,-314.401 2.38328,-279.599 14.3833,-267.599 119.617,-267.599 131.617,-279.599 131.617,-314.401 119.617,-326.401"></polygon>
<path fill="white" stroke="white" d="M14.3833,-326.401C8.38328,-326.401 2.38328,-320.401 2.38328,-314.401"></path>
<path fill="white" stroke="white" d="M2.38328,-279.599C2.38328,-273.599 8.38328,-267.599 14.3833,-267.599"></path>
<path fill="white" stroke="white" d="M119.617,-267.599C125.617,-267.599 131.617,-273.599 131.617,-279.599"></path>
<path fill="white" stroke="white" d="M131.617,-314.401C131.617,-320.401 125.617,-326.401 119.617,-326.401"></path>
<polyline fill="none" stroke="black" points="119.617,-326.401 14.3833,-326.401 "></polyline>
<path fill="none" stroke="black" d="M14.3833,-326.401C8.38328,-326.401 2.38328,-320.401 2.38328,-314.401"></path>
<polyline fill="none" stroke="black" points="2.38328,-314.401 2.38328,-279.599 "></polyline>
<path fill="none" stroke="black" d="M2.38328,-279.599C2.38328,-273.599 8.38328,-267.599 14.3833,-267.599"></path>
<polyline fill="none" stroke="black" points="14.3833,-267.599 119.617,-267.599 "></polyline>
<path fill="none" stroke="black" d="M119.617,-267.599C125.617,-267.599 131.617,-273.599 131.617,-279.599"></path>
<polyline fill="none" stroke="black" points="131.617,-279.599 131.617,-314.401 "></polyline>
<path fill="none" stroke="black" d="M131.617,-314.401C131.617,-320.401 125.617,-326.401 119.617,-326.401"></path>
<text text-anchor="middle" x="67" y="-309.6" font-family="Times,serif" font-size="14.00">VariableDeclaration</text>
<text text-anchor="middle" x="67" y="-292.8" font-family="Times,serif" font-size="14.00">VariableDeclarator</text>
<text text-anchor="middle" x="67" y="-276" font-family="Times,serif" font-size="14.00">Identifier (key)</text>
</g>
<g id="edge4" class="edge"><title>s1_3-&gt;s1_2</title>
<path fill="none" stroke="black" d="M104.033,-361.822C99.4992,-354.009 93.9468,-344.44 88.5344,-335.112"></path>
<polygon fill="black" stroke="black" points="91.4721,-333.201 83.4259,-326.309 85.4175,-336.715 91.4721,-333.201"></polygon>
</g>
<g id="node7" class="node"><title>s1_5</title>
<polygon fill="white" stroke="white" points="165.484,-103.602 62.5157,-103.602 50.5157,-91.6019 50.5157,-74.3981 62.5157,-62.3981 165.484,-62.3981 177.484,-74.3981 177.484,-91.6019 165.484,-103.602"></polygon>
<path fill="white" stroke="white" d="M62.5157,-103.602C56.5157,-103.602 50.5157,-97.6019 50.5157,-91.6019"></path>
<path fill="white" stroke="white" d="M50.5157,-74.3981C50.5157,-68.3981 56.5157,-62.3981 62.5157,-62.3981"></path>
<path fill="white" stroke="white" d="M165.484,-62.3981C171.484,-62.3981 177.484,-68.3981 177.484,-74.3981"></path>
<path fill="white" stroke="white" d="M177.484,-91.6019C177.484,-97.6019 171.484,-103.602 165.484,-103.602"></path>
<polyline fill="none" stroke="black" points="165.484,-103.602 62.5157,-103.602 "></polyline>
<path fill="none" stroke="black" d="M62.5157,-103.602C56.5157,-103.602 50.5157,-97.6019 50.5157,-91.6019"></path>
<polyline fill="none" stroke="black" points="50.5157,-91.6019 50.5157,-74.3981 "></polyline>
<path fill="none" stroke="black" d="M50.5157,-74.3981C50.5157,-68.3981 56.5157,-62.3981 62.5157,-62.3981"></path>
<polyline fill="none" stroke="black" points="62.5157,-62.3981 165.484,-62.3981 "></polyline>
<path fill="none" stroke="black" d="M165.484,-62.3981C171.484,-62.3981 177.484,-68.3981 177.484,-74.3981"></path>
<polyline fill="none" stroke="black" points="177.484,-74.3981 177.484,-91.6019 "></polyline>
<path fill="none" stroke="black" d="M177.484,-91.6019C177.484,-97.6019 171.484,-103.602 165.484,-103.602"></path>
<text text-anchor="middle" x="114" y="-87.2" font-family="Times,serif" font-size="14.00">ForInStatement:exit</text>
<text text-anchor="middle" x="114" y="-70.4" font-family="Times,serif" font-size="14.00">Program:exit</text>
</g>
<g id="edge8" class="edge"><title>s1_3-&gt;s1_5</title>
<path fill="none" stroke="black" d="M124.891,-361.573C130.533,-351.566 136.88,-338.531 140,-326 159.973,-245.771 162.566,-220.329 143,-140 140.717,-130.626 136.569,-121.069 132.111,-112.567"></path>
<polygon fill="black" stroke="black" points="135.155,-110.84 127.225,-103.814 129.043,-114.251 135.155,-110.84"></polygon>
</g>
<g id="node6" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="122.147,-232 11.8526,-232 -0.147372,-220 -0.147372,-152 11.8526,-140 122.147,-140 134.147,-152 134.147,-220 122.147,-232"></polygon>
<path fill="white" stroke="white" d="M11.8526,-232C5.85263,-232 -0.147372,-226 -0.147372,-220"></path>
<path fill="white" stroke="white" d="M-0.147372,-152C-0.147372,-146 5.85263,-140 11.8526,-140"></path>
<path fill="white" stroke="white" d="M122.147,-140C128.147,-140 134.147,-146 134.147,-152"></path>
<path fill="white" stroke="white" d="M134.147,-220C134.147,-226 128.147,-232 122.147,-232"></path>
<polyline fill="none" stroke="black" points="122.147,-232 11.8526,-232 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-232C5.85263,-232 -0.147372,-226 -0.147372,-220"></path>
<polyline fill="none" stroke="black" points="-0.147372,-220 -0.147372,-152 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-152C-0.147372,-146 5.85263,-140 11.8526,-140"></path>
<polyline fill="none" stroke="black" points="11.8526,-140 122.147,-140 "></polyline>
<path fill="none" stroke="black" d="M122.147,-140C128.147,-140 134.147,-146 134.147,-152"></path>
<polyline fill="none" stroke="black" points="134.147,-152 134.147,-220 "></polyline>
<path fill="none" stroke="black" d="M134.147,-220C134.147,-226 128.147,-232 122.147,-232"></path>
<text text-anchor="middle" x="67" y="-215.4" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-198.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-181.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-165" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="67" y="-148.2" font-family="Times,serif" font-size="14.00">Identifier (key)</text>
</g>
<g id="edge5" class="edge"><title>s1_2-&gt;s1_4</title>
<path fill="none" stroke="black" d="M60.9942,-267.646C60.5136,-259.848 60.2658,-251.114 60.2507,-242.351"></path>
<polygon fill="black" stroke="black" points="63.7527,-242.134 60.34,-232.104 56.7529,-242.073 63.7527,-242.134"></polygon>
</g>
<g id="edge6" class="edge"><title>s1_4-&gt;s1_2</title>
<path fill="none" stroke="black" d="M73.66,-232.104C73.8235,-240.564 73.7642,-249.334 73.4822,-257.568"></path>
<polygon fill="black" stroke="black" points="69.982,-257.492 73.0058,-267.646 76.9742,-257.823 69.982,-257.492"></polygon>
</g>
<g id="edge10" class="edge"><title>s1_4-&gt;s1_5</title>
<path fill="none" stroke="black" d="M88.0256,-139.817C92.2417,-130.757 96.5653,-121.466 100.445,-113.128"></path>
<polygon fill="black" stroke="black" points="103.718,-114.392 104.763,-103.849 97.3711,-111.439 103.718,-114.392"></polygon>
</g>
<g id="edge11" class="edge"><title>s1_5-&gt;final</title>
<path fill="none" stroke="black" d="M114,-62.3316C114,-54.2587 114,-44.8663 114,-36.5198"></path>
<polygon fill="black" stroke="black" points="117.5,-36.3487 114,-26.3488 110.5,-36.3488 117.5,-36.3487"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,63 @@
<?xml version="1.0"?>
<svg width="160pt" height="216pt" viewBox="0.00 0.00 160.00 216.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 212)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="67" cy="-199" rx="9" ry="9"></ellipse>
</g>
<g id="node2" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="100.573,-153.602 33.4267,-153.602 21.4267,-141.602 21.4267,-124.398 33.4267,-112.398 100.573,-112.398 112.573,-124.398 112.573,-141.602 100.573,-153.602"></polygon>
<path fill="white" stroke="white" d="M33.4267,-153.602C27.4267,-153.602 21.4267,-147.602 21.4267,-141.602"></path>
<path fill="white" stroke="white" d="M21.4267,-124.398C21.4267,-118.398 27.4267,-112.398 33.4267,-112.398"></path>
<path fill="white" stroke="white" d="M100.573,-112.398C106.573,-112.398 112.573,-118.398 112.573,-124.398"></path>
<path fill="white" stroke="white" d="M112.573,-141.602C112.573,-147.602 106.573,-153.602 100.573,-153.602"></path>
<polyline fill="none" stroke="black" points="100.573,-153.602 33.4267,-153.602 "></polyline>
<path fill="none" stroke="black" d="M33.4267,-153.602C27.4267,-153.602 21.4267,-147.602 21.4267,-141.602"></path>
<polyline fill="none" stroke="black" points="21.4267,-141.602 21.4267,-124.398 "></polyline>
<path fill="none" stroke="black" d="M21.4267,-124.398C21.4267,-118.398 27.4267,-112.398 33.4267,-112.398"></path>
<polyline fill="none" stroke="black" points="33.4267,-112.398 100.573,-112.398 "></polyline>
<path fill="none" stroke="black" d="M100.573,-112.398C106.573,-112.398 112.573,-118.398 112.573,-124.398"></path>
<polyline fill="none" stroke="black" points="112.573,-124.398 112.573,-141.602 "></polyline>
<path fill="none" stroke="black" d="M112.573,-141.602C112.573,-147.602 106.573,-153.602 100.573,-153.602"></path>
<text text-anchor="middle" x="67" y="-137.2" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="67" y="-120.4" font-family="Times,serif" font-size="14.00">ForStatement</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M67,-189.894C67,-183.274 67,-173.485 67,-163.94"></path>
<polygon fill="black" stroke="black" points="70.5001,-163.842 67,-153.842 63.5001,-163.842 70.5001,-163.842"></polygon>
</g>
<g id="node3" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="122.147,-75.7003 11.8526,-75.7003 -0.147372,-63.7003 -0.147372,-12.2997 11.8526,-0.299733 122.147,-0.299733 134.147,-12.2997 134.147,-63.7003 122.147,-75.7003"></polygon>
<path fill="white" stroke="white" d="M11.8526,-75.7003C5.85263,-75.7003 -0.147372,-69.7003 -0.147372,-63.7003"></path>
<path fill="white" stroke="white" d="M-0.147372,-12.2997C-0.147372,-6.29973 5.85263,-0.299733 11.8526,-0.299733"></path>
<path fill="white" stroke="white" d="M122.147,-0.299733C128.147,-0.299733 134.147,-6.29973 134.147,-12.2997"></path>
<path fill="white" stroke="white" d="M134.147,-63.7003C134.147,-69.7003 128.147,-75.7003 122.147,-75.7003"></path>
<polyline fill="none" stroke="black" points="122.147,-75.7003 11.8526,-75.7003 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-75.7003C5.85263,-75.7003 -0.147372,-69.7003 -0.147372,-63.7003"></path>
<polyline fill="none" stroke="black" points="-0.147372,-63.7003 -0.147372,-12.2997 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-12.2997C-0.147372,-6.29973 5.85263,-0.299733 11.8526,-0.299733"></path>
<polyline fill="none" stroke="black" points="11.8526,-0.299733 122.147,-0.299733 "></polyline>
<path fill="none" stroke="black" d="M122.147,-0.299733C128.147,-0.299733 134.147,-6.29973 134.147,-12.2997"></path>
<polyline fill="none" stroke="black" points="134.147,-12.2997 134.147,-63.7003 "></polyline>
<path fill="none" stroke="black" d="M134.147,-63.7003C134.147,-69.7003 128.147,-75.7003 122.147,-75.7003"></path>
<text text-anchor="middle" x="67" y="-59" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-42.2" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-25.4" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-8.6" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M67,-112.277C67,-104.524 67,-95.2648 67,-85.9799"></path>
<polygon fill="black" stroke="black" points="70.5001,-85.9648 67,-75.9648 63.5001,-85.9648 70.5001,-85.9648"></polygon>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_2</title>
<path fill="none" stroke="black" d="M134.337,-54.1523C144.84,-51.7376 152,-46.3535 152,-38 152,-32.518 148.916,-28.3148 143.828,-25.3905"></path>
<polygon fill="black" stroke="black" points="144.93,-22.0659 134.337,-21.8477 142.482,-28.6239 144.93,-22.0659"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,201 @@
<?xml version="1.0"?>
<svg width="350pt" height="646pt" viewBox="0.00 0.00 350.00 646.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 642)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="174" cy="-629" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="226.617,-583.3 121.383,-583.3 109.383,-571.3 109.383,-486.7 121.383,-474.7 226.617,-474.7 238.617,-486.7 238.617,-571.3 226.617,-583.3"></polygon>
<path fill="white" stroke="white" d="M121.383,-583.3C115.383,-583.3 109.383,-577.3 109.383,-571.3"></path>
<path fill="white" stroke="white" d="M109.383,-486.7C109.383,-480.7 115.383,-474.7 121.383,-474.7"></path>
<path fill="white" stroke="white" d="M226.617,-474.7C232.617,-474.7 238.617,-480.7 238.617,-486.7"></path>
<path fill="white" stroke="white" d="M238.617,-571.3C238.617,-577.3 232.617,-583.3 226.617,-583.3"></path>
<polyline fill="none" stroke="black" points="226.617,-583.3 121.383,-583.3 "></polyline>
<path fill="none" stroke="black" d="M121.383,-583.3C115.383,-583.3 109.383,-577.3 109.383,-571.3"></path>
<polyline fill="none" stroke="black" points="109.383,-571.3 109.383,-486.7 "></polyline>
<path fill="none" stroke="black" d="M109.383,-486.7C109.383,-480.7 115.383,-474.7 121.383,-474.7"></path>
<polyline fill="none" stroke="black" points="121.383,-474.7 226.617,-474.7 "></polyline>
<path fill="none" stroke="black" d="M226.617,-474.7C232.617,-474.7 238.617,-480.7 238.617,-486.7"></path>
<polyline fill="none" stroke="black" points="238.617,-486.7 238.617,-571.3 "></polyline>
<path fill="none" stroke="black" d="M238.617,-571.3C238.617,-577.3 232.617,-583.3 226.617,-583.3"></path>
<text text-anchor="middle" x="174" y="-566.8" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="174" y="-550" font-family="Times,serif" font-size="14.00">ForStatement</text>
<text text-anchor="middle" x="174" y="-533.2" font-family="Times,serif" font-size="14.00">VariableDeclaration</text>
<text text-anchor="middle" x="174" y="-516.4" font-family="Times,serif" font-size="14.00">VariableDeclarator</text>
<text text-anchor="middle" x="174" y="-499.6" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="174" y="-482.8" font-family="Times,serif" font-size="14.00">Literal (0)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M174,-619.98C174,-613.675 174,-604.238 174,-593.813"></path>
<polygon fill="black" stroke="black" points="177.5,-593.586 174,-583.586 170.5,-593.586 177.5,-593.586"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="58" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="58" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="220.233,-438.401 127.767,-438.401 115.767,-426.401 115.767,-391.599 127.767,-379.599 220.233,-379.599 232.233,-391.599 232.233,-426.401 220.233,-438.401"></polygon>
<path fill="white" stroke="white" d="M127.767,-438.401C121.767,-438.401 115.767,-432.401 115.767,-426.401"></path>
<path fill="white" stroke="white" d="M115.767,-391.599C115.767,-385.599 121.767,-379.599 127.767,-379.599"></path>
<path fill="white" stroke="white" d="M220.233,-379.599C226.233,-379.599 232.233,-385.599 232.233,-391.599"></path>
<path fill="white" stroke="white" d="M232.233,-426.401C232.233,-432.401 226.233,-438.401 220.233,-438.401"></path>
<polyline fill="none" stroke="black" points="220.233,-438.401 127.767,-438.401 "></polyline>
<path fill="none" stroke="black" d="M127.767,-438.401C121.767,-438.401 115.767,-432.401 115.767,-426.401"></path>
<polyline fill="none" stroke="black" points="115.767,-426.401 115.767,-391.599 "></polyline>
<path fill="none" stroke="black" d="M115.767,-391.599C115.767,-385.599 121.767,-379.599 127.767,-379.599"></path>
<polyline fill="none" stroke="black" points="127.767,-379.599 220.233,-379.599 "></polyline>
<path fill="none" stroke="black" d="M220.233,-379.599C226.233,-379.599 232.233,-385.599 232.233,-391.599"></path>
<polyline fill="none" stroke="black" points="232.233,-391.599 232.233,-426.401 "></polyline>
<path fill="none" stroke="black" d="M232.233,-426.401C232.233,-432.401 226.233,-438.401 220.233,-438.401"></path>
<text text-anchor="middle" x="174" y="-421.6" font-family="Times,serif" font-size="14.00">BinaryExpression</text>
<text text-anchor="middle" x="174" y="-404.8" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="174" y="-388" font-family="Times,serif" font-size="14.00">Literal (10)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M174,-474.524C174,-465.777 174,-456.867 174,-448.572"></path>
<polygon fill="black" stroke="black" points="177.5,-448.452 174,-438.452 170.5,-448.452 177.5,-448.452"></polygon>
</g>
<g id="node5" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="229.147,-343.3 118.853,-343.3 106.853,-331.3 106.853,-246.7 118.853,-234.7 229.147,-234.7 241.147,-246.7 241.147,-331.3 229.147,-343.3"></polygon>
<path fill="white" stroke="white" d="M118.853,-343.3C112.853,-343.3 106.853,-337.3 106.853,-331.3"></path>
<path fill="white" stroke="white" d="M106.853,-246.7C106.853,-240.7 112.853,-234.7 118.853,-234.7"></path>
<path fill="white" stroke="white" d="M229.147,-234.7C235.147,-234.7 241.147,-240.7 241.147,-246.7"></path>
<path fill="white" stroke="white" d="M241.147,-331.3C241.147,-337.3 235.147,-343.3 229.147,-343.3"></path>
<polyline fill="none" stroke="black" points="229.147,-343.3 118.853,-343.3 "></polyline>
<path fill="none" stroke="black" d="M118.853,-343.3C112.853,-343.3 106.853,-337.3 106.853,-331.3"></path>
<polyline fill="none" stroke="black" points="106.853,-331.3 106.853,-246.7 "></polyline>
<path fill="none" stroke="black" d="M106.853,-246.7C106.853,-240.7 112.853,-234.7 118.853,-234.7"></path>
<polyline fill="none" stroke="black" points="118.853,-234.7 229.147,-234.7 "></polyline>
<path fill="none" stroke="black" d="M229.147,-234.7C235.147,-234.7 241.147,-240.7 241.147,-246.7"></path>
<polyline fill="none" stroke="black" points="241.147,-246.7 241.147,-331.3 "></polyline>
<path fill="none" stroke="black" d="M241.147,-331.3C241.147,-337.3 235.147,-343.3 229.147,-343.3"></path>
<text text-anchor="middle" x="174" y="-326.8" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="174" y="-310" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="174" y="-293.2" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="174" y="-276.4" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="174" y="-259.6" font-family="Times,serif" font-size="14.00">IfStatement</text>
<text text-anchor="middle" x="174" y="-242.8" font-family="Times,serif" font-size="14.00">Identifier (b)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M174,-379.736C174,-371.725 174,-362.664 174,-353.458"></path>
<polygon fill="black" stroke="black" points="177.5,-353.454 174,-343.454 170.5,-353.454 177.5,-353.454"></polygon>
</g>
<g id="node9" class="node"><title>s1_8</title>
<polygon fill="white" stroke="white" points="104.239,-103.602 11.761,-103.602 -0.239018,-91.6019 -0.239018,-74.3981 11.761,-62.3981 104.239,-62.3981 116.239,-74.3981 116.239,-91.6019 104.239,-103.602"></polygon>
<path fill="white" stroke="white" d="M11.761,-103.602C5.76098,-103.602 -0.239018,-97.6019 -0.239018,-91.6019"></path>
<path fill="white" stroke="white" d="M-0.239018,-74.3981C-0.239018,-68.3981 5.76098,-62.3981 11.761,-62.3981"></path>
<path fill="white" stroke="white" d="M104.239,-62.3981C110.239,-62.3981 116.239,-68.3981 116.239,-74.3981"></path>
<path fill="white" stroke="white" d="M116.239,-91.6019C116.239,-97.6019 110.239,-103.602 104.239,-103.602"></path>
<polyline fill="none" stroke="black" points="104.239,-103.602 11.761,-103.602 "></polyline>
<path fill="none" stroke="black" d="M11.761,-103.602C5.76098,-103.602 -0.239018,-97.6019 -0.239018,-91.6019"></path>
<polyline fill="none" stroke="black" points="-0.239018,-91.6019 -0.239018,-74.3981 "></polyline>
<path fill="none" stroke="black" d="M-0.239018,-74.3981C-0.239018,-68.3981 5.76098,-62.3981 11.761,-62.3981"></path>
<polyline fill="none" stroke="black" points="11.761,-62.3981 104.239,-62.3981 "></polyline>
<path fill="none" stroke="black" d="M104.239,-62.3981C110.239,-62.3981 116.239,-68.3981 116.239,-74.3981"></path>
<polyline fill="none" stroke="black" points="116.239,-74.3981 116.239,-91.6019 "></polyline>
<path fill="none" stroke="black" d="M116.239,-91.6019C116.239,-97.6019 110.239,-103.602 104.239,-103.602"></path>
<text text-anchor="middle" x="58" y="-87.2" font-family="Times,serif" font-size="14.00">ForStatement:exit</text>
<text text-anchor="middle" x="58" y="-70.4" font-family="Times,serif" font-size="14.00">Program:exit</text>
</g>
<g id="edge9" class="edge"><title>s1_2-&gt;s1_8</title>
<path fill="none" stroke="black" d="M133.184,-379.539C120.713,-369.392 107.737,-357.181 98,-344 56.1121,-287.297 50.0603,-267.081 36,-198 30.8588,-172.74 31.2034,-165.328 36,-140 37.7044,-131.001 40.8223,-121.596 44.1855,-113.12"></path>
<polygon fill="black" stroke="black" points="47.5078,-114.249 48.1762,-103.676 41.0598,-111.525 47.5078,-114.249"></polygon>
</g>
<g id="node6" class="node"><title>s1_5</title>
<polygon fill="white" stroke="white" points="138.572,-189.602 57.4276,-189.602 45.4276,-177.602 45.4276,-160.398 57.4276,-148.398 138.572,-148.398 150.572,-160.398 150.572,-177.602 138.572,-189.602"></polygon>
<path fill="white" stroke="white" d="M57.4276,-189.602C51.4276,-189.602 45.4276,-183.602 45.4276,-177.602"></path>
<path fill="white" stroke="white" d="M45.4276,-160.398C45.4276,-154.398 51.4276,-148.398 57.4276,-148.398"></path>
<path fill="white" stroke="white" d="M138.572,-148.398C144.572,-148.398 150.572,-154.398 150.572,-160.398"></path>
<path fill="white" stroke="white" d="M150.572,-177.602C150.572,-183.602 144.572,-189.602 138.572,-189.602"></path>
<polyline fill="none" stroke="black" points="138.572,-189.602 57.4276,-189.602 "></polyline>
<path fill="none" stroke="black" d="M57.4276,-189.602C51.4276,-189.602 45.4276,-183.602 45.4276,-177.602"></path>
<polyline fill="none" stroke="black" points="45.4276,-177.602 45.4276,-160.398 "></polyline>
<path fill="none" stroke="black" d="M45.4276,-160.398C45.4276,-154.398 51.4276,-148.398 57.4276,-148.398"></path>
<polyline fill="none" stroke="black" points="57.4276,-148.398 138.572,-148.398 "></polyline>
<path fill="none" stroke="black" d="M138.572,-148.398C144.572,-148.398 150.572,-154.398 150.572,-160.398"></path>
<polyline fill="none" stroke="black" points="150.572,-160.398 150.572,-177.602 "></polyline>
<path fill="none" stroke="black" d="M150.572,-177.602C150.572,-183.602 144.572,-189.602 138.572,-189.602"></path>
<text text-anchor="middle" x="98" y="-173.2" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="98" y="-156.4" font-family="Times,serif" font-size="14.00">BreakStatement</text>
</g>
<g id="edge5" class="edge"><title>s1_3-&gt;s1_5</title>
<path fill="none" stroke="black" d="M139.558,-234.524C131.519,-222.042 123.266,-209.228 116.254,-198.342"></path>
<polygon fill="black" stroke="black" points="119.046,-196.213 110.689,-189.701 113.161,-200.003 119.046,-196.213"></polygon>
</g>
<g id="node7" class="node"><title>s1_7</title>
<polygon fill="white" stroke="white" points="291.147,-198.401 180.853,-198.401 168.853,-186.401 168.853,-151.599 180.853,-139.599 291.147,-139.599 303.147,-151.599 303.147,-186.401 291.147,-198.401"></polygon>
<path fill="white" stroke="white" d="M180.853,-198.401C174.853,-198.401 168.853,-192.401 168.853,-186.401"></path>
<path fill="white" stroke="white" d="M168.853,-151.599C168.853,-145.599 174.853,-139.599 180.853,-139.599"></path>
<path fill="white" stroke="white" d="M291.147,-139.599C297.147,-139.599 303.147,-145.599 303.147,-151.599"></path>
<path fill="white" stroke="white" d="M303.147,-186.401C303.147,-192.401 297.147,-198.401 291.147,-198.401"></path>
<polyline fill="none" stroke="black" points="291.147,-198.401 180.853,-198.401 "></polyline>
<path fill="none" stroke="black" d="M180.853,-198.401C174.853,-198.401 168.853,-192.401 168.853,-186.401"></path>
<polyline fill="none" stroke="black" points="168.853,-186.401 168.853,-151.599 "></polyline>
<path fill="none" stroke="black" d="M168.853,-151.599C168.853,-145.599 174.853,-139.599 180.853,-139.599"></path>
<polyline fill="none" stroke="black" points="180.853,-139.599 291.147,-139.599 "></polyline>
<path fill="none" stroke="black" d="M291.147,-139.599C297.147,-139.599 303.147,-145.599 303.147,-151.599"></path>
<polyline fill="none" stroke="black" points="303.147,-151.599 303.147,-186.401 "></polyline>
<path fill="none" stroke="black" d="M303.147,-186.401C303.147,-192.401 297.147,-198.401 291.147,-198.401"></path>
<text text-anchor="middle" x="236" y="-181.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="236" y="-164.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="236" y="-148" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge11" class="edge"><title>s1_3-&gt;s1_7</title>
<path fill="none" stroke="black" d="M202.098,-234.524C206.898,-225.389 211.791,-216.075 216.313,-207.47"></path>
<polygon fill="black" stroke="black" points="219.498,-208.932 221.051,-198.452 213.301,-205.676 219.498,-208.932"></polygon>
</g>
<g id="edge13" class="edge"><title>s1_5-&gt;s1_8</title>
<path fill="none" stroke="black" d="M88.5206,-148.093C83.5391,-137.632 77.3402,-124.615 71.833,-113.049"></path>
<polygon fill="black" stroke="black" points="74.8708,-111.288 67.4114,-103.764 68.5508,-114.297 74.8708,-111.288"></polygon>
</g>
<g id="node8" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="329.977,-103.602 236.023,-103.602 224.023,-91.6019 224.023,-74.3981 236.023,-62.3981 329.977,-62.3981 341.977,-74.3981 341.977,-91.6019 329.977,-103.602"></polygon>
<path fill="white" stroke="white" d="M236.023,-103.602C230.023,-103.602 224.023,-97.6019 224.023,-91.6019"></path>
<path fill="white" stroke="white" d="M224.023,-74.3981C224.023,-68.3981 230.023,-62.3981 236.023,-62.3981"></path>
<path fill="white" stroke="white" d="M329.977,-62.3981C335.977,-62.3981 341.977,-68.3981 341.977,-74.3981"></path>
<path fill="white" stroke="white" d="M341.977,-91.6019C341.977,-97.6019 335.977,-103.602 329.977,-103.602"></path>
<polyline fill="none" stroke="black" points="329.977,-103.602 236.023,-103.602 "></polyline>
<path fill="none" stroke="black" d="M236.023,-103.602C230.023,-103.602 224.023,-97.6019 224.023,-91.6019"></path>
<polyline fill="none" stroke="black" points="224.023,-91.6019 224.023,-74.3981 "></polyline>
<path fill="none" stroke="black" d="M224.023,-74.3981C224.023,-68.3981 230.023,-62.3981 236.023,-62.3981"></path>
<polyline fill="none" stroke="black" points="236.023,-62.3981 329.977,-62.3981 "></polyline>
<path fill="none" stroke="black" d="M329.977,-62.3981C335.977,-62.3981 341.977,-68.3981 341.977,-74.3981"></path>
<polyline fill="none" stroke="black" points="341.977,-74.3981 341.977,-91.6019 "></polyline>
<path fill="none" stroke="black" d="M341.977,-91.6019C341.977,-97.6019 335.977,-103.602 329.977,-103.602"></path>
<text text-anchor="middle" x="283" y="-87.2" font-family="Times,serif" font-size="14.00">UpdateExpression</text>
<text text-anchor="middle" x="283" y="-70.4" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
</g>
<g id="edge7" class="edge"><title>s1_7-&gt;s1_4</title>
<path fill="none" stroke="black" d="M251.912,-139.561C256.814,-130.801 262.209,-121.158 267.109,-112.4"></path>
<polygon fill="black" stroke="black" points="270.167,-114.104 271.995,-103.668 264.058,-110.686 270.167,-114.104"></polygon>
</g>
<g id="edge8" class="edge"><title>s1_4-&gt;s1_2</title>
<path fill="none" stroke="black" d="M296.225,-103.814C302.324,-114.132 308.891,-127.235 312,-140 318.1,-165.046 317.141,-172.74 312,-198 297.94,-267.081 291.888,-287.297 250,-344 242.317,-354.4 232.617,-364.197 222.74,-372.853"></path>
<polygon fill="black" stroke="black" points="220.202,-370.415 214.816,-379.539 224.716,-375.765 220.202,-370.415"></polygon>
</g>
<g id="edge14" class="edge"><title>s1_8-&gt;final</title>
<path fill="none" stroke="black" d="M58,-62.3316C58,-54.2587 58,-44.8663 58,-36.5198"></path>
<polygon fill="black" stroke="black" points="61.5001,-36.3487 58,-26.3488 54.5001,-36.3488 61.5001,-36.3487"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,48 @@
<?xml version="1.0"?>
<svg width="146pt" height="250pt" viewBox="0.00 0.00 146.00 250.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 246)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="69" cy="-233" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="126.042,-187.601 11.9578,-187.601 -0.0421557,-175.601 -0.0421557,-74.3994 11.9578,-62.3994 126.042,-62.3994 138.042,-74.3994 138.042,-175.601 126.042,-187.601"></polygon>
<path fill="white" stroke="white" d="M11.9578,-187.601C5.95784,-187.601 -0.0421557,-181.601 -0.0421557,-175.601"></path>
<path fill="white" stroke="white" d="M-0.0421557,-74.3994C-0.0421557,-68.3994 5.95784,-62.3994 11.9578,-62.3994"></path>
<path fill="white" stroke="white" d="M126.042,-62.3994C132.042,-62.3994 138.042,-68.3994 138.042,-74.3994"></path>
<path fill="white" stroke="white" d="M138.042,-175.601C138.042,-181.601 132.042,-187.601 126.042,-187.601"></path>
<polyline fill="none" stroke="black" points="126.042,-187.601 11.9578,-187.601 "></polyline>
<path fill="none" stroke="black" d="M11.9578,-187.601C5.95784,-187.601 -0.0421557,-181.601 -0.0421557,-175.601"></path>
<polyline fill="none" stroke="black" points="-0.0421557,-175.601 -0.0421557,-74.3994 "></polyline>
<path fill="none" stroke="black" d="M-0.0421557,-74.3994C-0.0421557,-68.3994 5.95784,-62.3994 11.9578,-62.3994"></path>
<polyline fill="none" stroke="black" points="11.9578,-62.3994 126.042,-62.3994 "></polyline>
<path fill="none" stroke="black" d="M126.042,-62.3994C132.042,-62.3994 138.042,-68.3994 138.042,-74.3994"></path>
<polyline fill="none" stroke="black" points="138.042,-74.3994 138.042,-175.601 "></polyline>
<path fill="none" stroke="black" d="M138.042,-175.601C138.042,-181.601 132.042,-187.601 126.042,-187.601"></path>
<text text-anchor="middle" x="69" y="-171.2" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="69" y="-154.4" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="69" y="-137.6" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="69" y="-120.8" font-family="Times,serif" font-size="14.00">MemberExpression</text>
<text text-anchor="middle" x="69" y="-104" font-family="Times,serif" font-size="14.00">Identifier (console)</text>
<text text-anchor="middle" x="69" y="-87.2" font-family="Times,serif" font-size="14.00">Identifier (log)</text>
<text text-anchor="middle" x="69" y="-70.4" font-family="Times,serif" font-size="14.00">Literal (Hello world!)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M69,-223.682C69,-217.432 69,-208.196 69,-197.86"></path>
<polygon fill="black" stroke="black" points="72.5001,-197.675 69,-187.675 65.5001,-197.675 72.5001,-197.675"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="69" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="69" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;final</title>
<path fill="none" stroke="black" d="M69,-62.2476C69,-53.0345 69,-44.0781 69,-36.4335"></path>
<polygon fill="black" stroke="black" points="72.5001,-36.2949 69,-26.2949 65.5001,-36.2949 72.5001,-36.2949"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,203 @@
<?xml version="1.0"?>
<svg width="371pt" height="562pt" viewBox="0.00 0.00 371.00 562.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 558)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="114" cy="-545" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="145.339,-500.401 82.6614,-500.401 70.6614,-488.401 70.6614,-453.599 82.6614,-441.599 145.339,-441.599 157.339,-453.599 157.339,-488.401 145.339,-500.401"></polygon>
<path fill="white" stroke="white" d="M82.6614,-500.401C76.6614,-500.401 70.6614,-494.401 70.6614,-488.401"></path>
<path fill="white" stroke="white" d="M70.6614,-453.599C70.6614,-447.599 76.6614,-441.599 82.6614,-441.599"></path>
<path fill="white" stroke="white" d="M145.339,-441.599C151.339,-441.599 157.339,-447.599 157.339,-453.599"></path>
<path fill="white" stroke="white" d="M157.339,-488.401C157.339,-494.401 151.339,-500.401 145.339,-500.401"></path>
<polyline fill="none" stroke="black" points="145.339,-500.401 82.6614,-500.401 "></polyline>
<path fill="none" stroke="black" d="M82.6614,-500.401C76.6614,-500.401 70.6614,-494.401 70.6614,-488.401"></path>
<polyline fill="none" stroke="black" points="70.6614,-488.401 70.6614,-453.599 "></polyline>
<path fill="none" stroke="black" d="M70.6614,-453.599C70.6614,-447.599 76.6614,-441.599 82.6614,-441.599"></path>
<polyline fill="none" stroke="black" points="82.6614,-441.599 145.339,-441.599 "></polyline>
<path fill="none" stroke="black" d="M145.339,-441.599C151.339,-441.599 157.339,-447.599 157.339,-453.599"></path>
<polyline fill="none" stroke="black" points="157.339,-453.599 157.339,-488.401 "></polyline>
<path fill="none" stroke="black" d="M157.339,-488.401C157.339,-494.401 151.339,-500.401 145.339,-500.401"></path>
<text text-anchor="middle" x="114" y="-483.6" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="114" y="-466.8" font-family="Times,serif" font-size="14.00">IfStatement</text>
<text text-anchor="middle" x="114" y="-450" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M114,-535.741C114,-529.393 114,-520.126 114,-510.615"></path>
<polygon fill="black" stroke="black" points="117.5,-510.324 114,-500.324 110.5,-510.324 117.5,-510.324"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="181" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="181" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="122.147,-215.7 11.8526,-215.7 -0.147372,-203.7 -0.147372,-152.3 11.8526,-140.3 122.147,-140.3 134.147,-152.3 134.147,-203.7 122.147,-215.7"></polygon>
<path fill="white" stroke="white" d="M11.8526,-215.7C5.85263,-215.7 -0.147372,-209.7 -0.147372,-203.7"></path>
<path fill="white" stroke="white" d="M-0.147372,-152.3C-0.147372,-146.3 5.85263,-140.3 11.8526,-140.3"></path>
<path fill="white" stroke="white" d="M122.147,-140.3C128.147,-140.3 134.147,-146.3 134.147,-152.3"></path>
<path fill="white" stroke="white" d="M134.147,-203.7C134.147,-209.7 128.147,-215.7 122.147,-215.7"></path>
<polyline fill="none" stroke="black" points="122.147,-215.7 11.8526,-215.7 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-215.7C5.85263,-215.7 -0.147372,-209.7 -0.147372,-203.7"></path>
<polyline fill="none" stroke="black" points="-0.147372,-203.7 -0.147372,-152.3 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-152.3C-0.147372,-146.3 5.85263,-140.3 11.8526,-140.3"></path>
<polyline fill="none" stroke="black" points="11.8526,-140.3 122.147,-140.3 "></polyline>
<path fill="none" stroke="black" d="M122.147,-140.3C128.147,-140.3 134.147,-146.3 134.147,-152.3"></path>
<polyline fill="none" stroke="black" points="134.147,-152.3 134.147,-203.7 "></polyline>
<path fill="none" stroke="black" d="M134.147,-203.7C134.147,-209.7 128.147,-215.7 122.147,-215.7"></path>
<text text-anchor="middle" x="67" y="-199" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-182.2" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-165.4" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-148.6" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M107.798,-441.544C101.706,-412.948 92.4152,-367.562 86,-328 80.4738,-293.921 75.5819,-255.241 72.1462,-225.832"></path>
<polygon fill="black" stroke="black" points="75.6165,-225.373 70.993,-215.84 68.6626,-226.175 75.6165,-225.373"></polygon>
</g>
<g id="node6" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="193.429,-405.602 130.571,-405.602 118.571,-393.602 118.571,-376.398 130.571,-364.398 193.429,-364.398 205.429,-376.398 205.429,-393.602 193.429,-405.602"></polygon>
<path fill="white" stroke="white" d="M130.571,-405.602C124.571,-405.602 118.571,-399.602 118.571,-393.602"></path>
<path fill="white" stroke="white" d="M118.571,-376.398C118.571,-370.398 124.571,-364.398 130.571,-364.398"></path>
<path fill="white" stroke="white" d="M193.429,-364.398C199.429,-364.398 205.429,-370.398 205.429,-376.398"></path>
<path fill="white" stroke="white" d="M205.429,-393.602C205.429,-399.602 199.429,-405.602 193.429,-405.602"></path>
<polyline fill="none" stroke="black" points="193.429,-405.602 130.571,-405.602 "></polyline>
<path fill="none" stroke="black" d="M130.571,-405.602C124.571,-405.602 118.571,-399.602 118.571,-393.602"></path>
<polyline fill="none" stroke="black" points="118.571,-393.602 118.571,-376.398 "></polyline>
<path fill="none" stroke="black" d="M118.571,-376.398C118.571,-370.398 124.571,-364.398 130.571,-364.398"></path>
<polyline fill="none" stroke="black" points="130.571,-364.398 193.429,-364.398 "></polyline>
<path fill="none" stroke="black" d="M193.429,-364.398C199.429,-364.398 205.429,-370.398 205.429,-376.398"></path>
<polyline fill="none" stroke="black" points="205.429,-376.398 205.429,-393.602 "></polyline>
<path fill="none" stroke="black" d="M205.429,-393.602C205.429,-399.602 199.429,-405.602 193.429,-405.602"></path>
<text text-anchor="middle" x="162" y="-389.2" font-family="Times,serif" font-size="14.00">IfStatement</text>
<text text-anchor="middle" x="162" y="-372.4" font-family="Times,serif" font-size="14.00">Identifier (b)</text>
</g>
<g id="edge6" class="edge"><title>s1_1-&gt;s1_3</title>
<path fill="none" stroke="black" d="M130.251,-441.561C135.257,-432.801 140.767,-423.158 145.771,-414.4"></path>
<polygon fill="black" stroke="black" points="148.839,-416.087 150.761,-405.668 142.761,-412.614 148.839,-416.087"></polygon>
</g>
<g id="node5" class="node"><title>s1_9</title>
<polygon fill="white" stroke="white" points="222.147,-103.602 139.853,-103.602 127.853,-91.6019 127.853,-74.3981 139.853,-62.3981 222.147,-62.3981 234.147,-74.3981 234.147,-91.6019 222.147,-103.602"></polygon>
<path fill="white" stroke="white" d="M139.853,-103.602C133.853,-103.602 127.853,-97.6019 127.853,-91.6019"></path>
<path fill="white" stroke="white" d="M127.853,-74.3981C127.853,-68.3981 133.853,-62.3981 139.853,-62.3981"></path>
<path fill="white" stroke="white" d="M222.147,-62.3981C228.147,-62.3981 234.147,-68.3981 234.147,-74.3981"></path>
<path fill="white" stroke="white" d="M234.147,-91.6019C234.147,-97.6019 228.147,-103.602 222.147,-103.602"></path>
<polyline fill="none" stroke="black" points="222.147,-103.602 139.853,-103.602 "></polyline>
<path fill="none" stroke="black" d="M139.853,-103.602C133.853,-103.602 127.853,-97.6019 127.853,-91.6019"></path>
<polyline fill="none" stroke="black" points="127.853,-91.6019 127.853,-74.3981 "></polyline>
<path fill="none" stroke="black" d="M127.853,-74.3981C127.853,-68.3981 133.853,-62.3981 139.853,-62.3981"></path>
<polyline fill="none" stroke="black" points="139.853,-62.3981 222.147,-62.3981 "></polyline>
<path fill="none" stroke="black" d="M222.147,-62.3981C228.147,-62.3981 234.147,-68.3981 234.147,-74.3981"></path>
<polyline fill="none" stroke="black" points="234.147,-74.3981 234.147,-91.6019 "></polyline>
<path fill="none" stroke="black" d="M234.147,-91.6019C234.147,-97.6019 228.147,-103.602 222.147,-103.602"></path>
<text text-anchor="middle" x="181" y="-87.2" font-family="Times,serif" font-size="14.00">IfStatement:exit</text>
<text text-anchor="middle" x="181" y="-70.4" font-family="Times,serif" font-size="14.00">Program:exit</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_9</title>
<path fill="none" stroke="black" d="M112.056,-140.244C124.376,-130.194 137.475,-119.507 148.909,-110.179"></path>
<polygon fill="black" stroke="black" points="151.37,-112.689 156.906,-103.655 146.945,-107.265 151.37,-112.689"></polygon>
</g>
<g id="edge15" class="edge"><title>s1_9-&gt;final</title>
<path fill="none" stroke="black" d="M181,-62.3316C181,-54.2587 181,-44.8663 181,-36.5198"></path>
<polygon fill="black" stroke="black" points="184.5,-36.3487 181,-26.3488 177.5,-36.3488 184.5,-36.3487"></polygon>
</g>
<g id="node7" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="217.147,-327.7 106.853,-327.7 94.8526,-315.7 94.8526,-264.3 106.853,-252.3 217.147,-252.3 229.147,-264.3 229.147,-315.7 217.147,-327.7"></polygon>
<path fill="white" stroke="white" d="M106.853,-327.7C100.853,-327.7 94.8526,-321.7 94.8526,-315.7"></path>
<path fill="white" stroke="white" d="M94.8526,-264.3C94.8526,-258.3 100.853,-252.3 106.853,-252.3"></path>
<path fill="white" stroke="white" d="M217.147,-252.3C223.147,-252.3 229.147,-258.3 229.147,-264.3"></path>
<path fill="white" stroke="white" d="M229.147,-315.7C229.147,-321.7 223.147,-327.7 217.147,-327.7"></path>
<polyline fill="none" stroke="black" points="217.147,-327.7 106.853,-327.7 "></polyline>
<path fill="none" stroke="black" d="M106.853,-327.7C100.853,-327.7 94.8526,-321.7 94.8526,-315.7"></path>
<polyline fill="none" stroke="black" points="94.8526,-315.7 94.8526,-264.3 "></polyline>
<path fill="none" stroke="black" d="M94.8526,-264.3C94.8526,-258.3 100.853,-252.3 106.853,-252.3"></path>
<polyline fill="none" stroke="black" points="106.853,-252.3 217.147,-252.3 "></polyline>
<path fill="none" stroke="black" d="M217.147,-252.3C223.147,-252.3 229.147,-258.3 229.147,-264.3"></path>
<polyline fill="none" stroke="black" points="229.147,-264.3 229.147,-315.7 "></polyline>
<path fill="none" stroke="black" d="M229.147,-315.7C229.147,-321.7 223.147,-327.7 217.147,-327.7"></path>
<text text-anchor="middle" x="162" y="-311" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="162" y="-294.2" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="162" y="-277.4" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="162" y="-260.6" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge7" class="edge"><title>s1_3-&gt;s1_4</title>
<path fill="none" stroke="black" d="M162,-364.277C162,-356.524 162,-347.265 162,-337.98"></path>
<polygon fill="black" stroke="black" points="165.5,-337.965 162,-327.965 158.5,-337.965 165.5,-337.965"></polygon>
</g>
<g id="node8" class="node"><title>s1_5</title>
<polygon fill="white" stroke="white" points="322.339,-310.602 259.661,-310.602 247.661,-298.602 247.661,-281.398 259.661,-269.398 322.339,-269.398 334.339,-281.398 334.339,-298.602 322.339,-310.602"></polygon>
<path fill="white" stroke="white" d="M259.661,-310.602C253.661,-310.602 247.661,-304.602 247.661,-298.602"></path>
<path fill="white" stroke="white" d="M247.661,-281.398C247.661,-275.398 253.661,-269.398 259.661,-269.398"></path>
<path fill="white" stroke="white" d="M322.339,-269.398C328.339,-269.398 334.339,-275.398 334.339,-281.398"></path>
<path fill="white" stroke="white" d="M334.339,-298.602C334.339,-304.602 328.339,-310.602 322.339,-310.602"></path>
<polyline fill="none" stroke="black" points="322.339,-310.602 259.661,-310.602 "></polyline>
<path fill="none" stroke="black" d="M259.661,-310.602C253.661,-310.602 247.661,-304.602 247.661,-298.602"></path>
<polyline fill="none" stroke="black" points="247.661,-298.602 247.661,-281.398 "></polyline>
<path fill="none" stroke="black" d="M247.661,-281.398C247.661,-275.398 253.661,-269.398 259.661,-269.398"></path>
<polyline fill="none" stroke="black" points="259.661,-269.398 322.339,-269.398 "></polyline>
<path fill="none" stroke="black" d="M322.339,-269.398C328.339,-269.398 334.339,-275.398 334.339,-281.398"></path>
<polyline fill="none" stroke="black" points="334.339,-281.398 334.339,-298.602 "></polyline>
<path fill="none" stroke="black" d="M334.339,-298.602C334.339,-304.602 328.339,-310.602 322.339,-310.602"></path>
<text text-anchor="middle" x="291" y="-294.2" font-family="Times,serif" font-size="14.00">IfStatement</text>
<text text-anchor="middle" x="291" y="-277.4" font-family="Times,serif" font-size="14.00">Identifier (c)</text>
</g>
<g id="edge10" class="edge"><title>s1_3-&gt;s1_5</title>
<path fill="none" stroke="black" d="M189.358,-364.277C208.598,-350.406 234.528,-331.712 255.382,-316.678"></path>
<polygon fill="black" stroke="black" points="257.617,-319.382 263.682,-310.694 253.523,-313.703 257.617,-319.382"></polygon>
</g>
<g id="edge8" class="edge"><title>s1_4-&gt;s1_9</title>
<path fill="none" stroke="black" d="M165.397,-252.35C169.069,-212.728 174.851,-150.341 178.25,-113.673"></path>
<polygon fill="black" stroke="black" points="181.744,-113.893 179.182,-103.613 174.774,-113.247 181.744,-113.893"></polygon>
</g>
<g id="edge14" class="edge"><title>s1_5-&gt;s1_9</title>
<path fill="none" stroke="black" d="M266.084,-269.392C250.495,-255.908 231.136,-236.742 219,-216 200.205,-183.878 190.203,-141.864 185.259,-113.957"></path>
<polygon fill="black" stroke="black" points="188.697,-113.293 183.604,-104.002 181.791,-114.441 188.697,-113.293"></polygon>
</g>
<g id="node9" class="node"><title>s1_6</title>
<polygon fill="white" stroke="white" points="350.147,-215.7 239.853,-215.7 227.853,-203.7 227.853,-152.3 239.853,-140.3 350.147,-140.3 362.147,-152.3 362.147,-203.7 350.147,-215.7"></polygon>
<path fill="white" stroke="white" d="M239.853,-215.7C233.853,-215.7 227.853,-209.7 227.853,-203.7"></path>
<path fill="white" stroke="white" d="M227.853,-152.3C227.853,-146.3 233.853,-140.3 239.853,-140.3"></path>
<path fill="white" stroke="white" d="M350.147,-140.3C356.147,-140.3 362.147,-146.3 362.147,-152.3"></path>
<path fill="white" stroke="white" d="M362.147,-203.7C362.147,-209.7 356.147,-215.7 350.147,-215.7"></path>
<polyline fill="none" stroke="black" points="350.147,-215.7 239.853,-215.7 "></polyline>
<path fill="none" stroke="black" d="M239.853,-215.7C233.853,-215.7 227.853,-209.7 227.853,-203.7"></path>
<polyline fill="none" stroke="black" points="227.853,-203.7 227.853,-152.3 "></polyline>
<path fill="none" stroke="black" d="M227.853,-152.3C227.853,-146.3 233.853,-140.3 239.853,-140.3"></path>
<polyline fill="none" stroke="black" points="239.853,-140.3 350.147,-140.3 "></polyline>
<path fill="none" stroke="black" d="M350.147,-140.3C356.147,-140.3 362.147,-146.3 362.147,-152.3"></path>
<polyline fill="none" stroke="black" points="362.147,-152.3 362.147,-203.7 "></polyline>
<path fill="none" stroke="black" d="M362.147,-203.7C362.147,-209.7 356.147,-215.7 350.147,-215.7"></path>
<text text-anchor="middle" x="295" y="-199" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="295" y="-182.2" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="295" y="-165.4" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="295" y="-148.6" font-family="Times,serif" font-size="14.00">Identifier (hoge)</text>
</g>
<g id="edge11" class="edge"><title>s1_5-&gt;s1_6</title>
<path fill="none" stroke="black" d="M291.715,-269.334C292.153,-257.284 292.734,-241.309 293.286,-226.147"></path>
<polygon fill="black" stroke="black" points="296.795,-225.959 293.66,-215.839 289.799,-225.705 296.795,-225.959"></polygon>
</g>
<g id="edge12" class="edge"><title>s1_6-&gt;s1_9</title>
<path fill="none" stroke="black" d="M249.944,-140.244C237.624,-130.194 224.525,-119.507 213.091,-110.179"></path>
<polygon fill="black" stroke="black" points="215.055,-107.265 205.094,-103.655 210.63,-112.689 215.055,-107.265"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,122 @@
<?xml version="1.0"?>
<svg width="294pt" height="372pt" viewBox="0.00 0.00 294.00 372.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 368)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="143" cy="-355" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="174.339,-310.401 111.661,-310.401 99.6614,-298.401 99.6614,-263.599 111.661,-251.599 174.339,-251.599 186.339,-263.599 186.339,-298.401 174.339,-310.401"></polygon>
<path fill="white" stroke="white" d="M111.661,-310.401C105.661,-310.401 99.6614,-304.401 99.6614,-298.401"></path>
<path fill="white" stroke="white" d="M99.6614,-263.599C99.6614,-257.599 105.661,-251.599 111.661,-251.599"></path>
<path fill="white" stroke="white" d="M174.339,-251.599C180.339,-251.599 186.339,-257.599 186.339,-263.599"></path>
<path fill="white" stroke="white" d="M186.339,-298.401C186.339,-304.401 180.339,-310.401 174.339,-310.401"></path>
<polyline fill="none" stroke="black" points="174.339,-310.401 111.661,-310.401 "></polyline>
<path fill="none" stroke="black" d="M111.661,-310.401C105.661,-310.401 99.6614,-304.401 99.6614,-298.401"></path>
<polyline fill="none" stroke="black" points="99.6614,-298.401 99.6614,-263.599 "></polyline>
<path fill="none" stroke="black" d="M99.6614,-263.599C99.6614,-257.599 105.661,-251.599 111.661,-251.599"></path>
<polyline fill="none" stroke="black" points="111.661,-251.599 174.339,-251.599 "></polyline>
<path fill="none" stroke="black" d="M174.339,-251.599C180.339,-251.599 186.339,-257.599 186.339,-263.599"></path>
<polyline fill="none" stroke="black" points="186.339,-263.599 186.339,-298.401 "></polyline>
<path fill="none" stroke="black" d="M186.339,-298.401C186.339,-304.401 180.339,-310.401 174.339,-310.401"></path>
<text text-anchor="middle" x="143" y="-293.6" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="143" y="-276.8" font-family="Times,serif" font-size="14.00">IfStatement</text>
<text text-anchor="middle" x="143" y="-260" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M143,-345.741C143,-339.393 143,-330.126 143,-320.615"></path>
<polygon fill="black" stroke="black" points="146.5,-320.324 143,-310.324 139.5,-320.324 146.5,-320.324"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="143" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="143" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="122.147,-215.7 11.8526,-215.7 -0.147372,-203.7 -0.147372,-152.3 11.8526,-140.3 122.147,-140.3 134.147,-152.3 134.147,-203.7 122.147,-215.7"></polygon>
<path fill="white" stroke="white" d="M11.8526,-215.7C5.85263,-215.7 -0.147372,-209.7 -0.147372,-203.7"></path>
<path fill="white" stroke="white" d="M-0.147372,-152.3C-0.147372,-146.3 5.85263,-140.3 11.8526,-140.3"></path>
<path fill="white" stroke="white" d="M122.147,-140.3C128.147,-140.3 134.147,-146.3 134.147,-152.3"></path>
<path fill="white" stroke="white" d="M134.147,-203.7C134.147,-209.7 128.147,-215.7 122.147,-215.7"></path>
<polyline fill="none" stroke="black" points="122.147,-215.7 11.8526,-215.7 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-215.7C5.85263,-215.7 -0.147372,-209.7 -0.147372,-203.7"></path>
<polyline fill="none" stroke="black" points="-0.147372,-203.7 -0.147372,-152.3 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-152.3C-0.147372,-146.3 5.85263,-140.3 11.8526,-140.3"></path>
<polyline fill="none" stroke="black" points="11.8526,-140.3 122.147,-140.3 "></polyline>
<path fill="none" stroke="black" d="M122.147,-140.3C128.147,-140.3 134.147,-146.3 134.147,-152.3"></path>
<polyline fill="none" stroke="black" points="134.147,-152.3 134.147,-203.7 "></polyline>
<path fill="none" stroke="black" d="M134.147,-203.7C134.147,-209.7 128.147,-215.7 122.147,-215.7"></path>
<text text-anchor="middle" x="67" y="-199" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-182.2" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-165.4" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-148.6" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M121.628,-251.597C115.176,-243.023 107.927,-233.39 100.871,-224.013"></path>
<polygon fill="black" stroke="black" points="103.554,-221.757 94.7444,-215.871 97.9604,-225.966 103.554,-221.757"></polygon>
</g>
<g id="node6" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="274.147,-215.7 163.853,-215.7 151.853,-203.7 151.853,-152.3 163.853,-140.3 274.147,-140.3 286.147,-152.3 286.147,-203.7 274.147,-215.7"></polygon>
<path fill="white" stroke="white" d="M163.853,-215.7C157.853,-215.7 151.853,-209.7 151.853,-203.7"></path>
<path fill="white" stroke="white" d="M151.853,-152.3C151.853,-146.3 157.853,-140.3 163.853,-140.3"></path>
<path fill="white" stroke="white" d="M274.147,-140.3C280.147,-140.3 286.147,-146.3 286.147,-152.3"></path>
<path fill="white" stroke="white" d="M286.147,-203.7C286.147,-209.7 280.147,-215.7 274.147,-215.7"></path>
<polyline fill="none" stroke="black" points="274.147,-215.7 163.853,-215.7 "></polyline>
<path fill="none" stroke="black" d="M163.853,-215.7C157.853,-215.7 151.853,-209.7 151.853,-203.7"></path>
<polyline fill="none" stroke="black" points="151.853,-203.7 151.853,-152.3 "></polyline>
<path fill="none" stroke="black" d="M151.853,-152.3C151.853,-146.3 157.853,-140.3 163.853,-140.3"></path>
<polyline fill="none" stroke="black" points="163.853,-140.3 274.147,-140.3 "></polyline>
<path fill="none" stroke="black" d="M274.147,-140.3C280.147,-140.3 286.147,-146.3 286.147,-152.3"></path>
<polyline fill="none" stroke="black" points="286.147,-152.3 286.147,-203.7 "></polyline>
<path fill="none" stroke="black" d="M286.147,-203.7C286.147,-209.7 280.147,-215.7 274.147,-215.7"></path>
<text text-anchor="middle" x="219" y="-199" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="219" y="-182.2" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="219" y="-165.4" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="219" y="-148.6" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge6" class="edge"><title>s1_1-&gt;s1_3</title>
<path fill="none" stroke="black" d="M164.372,-251.597C170.824,-243.023 178.073,-233.39 185.129,-224.013"></path>
<polygon fill="black" stroke="black" points="188.04,-225.966 191.256,-215.871 182.446,-221.757 188.04,-225.966"></polygon>
</g>
<g id="node5" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="184.147,-103.602 101.853,-103.602 89.8526,-91.6019 89.8526,-74.3981 101.853,-62.3981 184.147,-62.3981 196.147,-74.3981 196.147,-91.6019 184.147,-103.602"></polygon>
<path fill="white" stroke="white" d="M101.853,-103.602C95.8526,-103.602 89.8526,-97.6019 89.8526,-91.6019"></path>
<path fill="white" stroke="white" d="M89.8526,-74.3981C89.8526,-68.3981 95.8526,-62.3981 101.853,-62.3981"></path>
<path fill="white" stroke="white" d="M184.147,-62.3981C190.147,-62.3981 196.147,-68.3981 196.147,-74.3981"></path>
<path fill="white" stroke="white" d="M196.147,-91.6019C196.147,-97.6019 190.147,-103.602 184.147,-103.602"></path>
<polyline fill="none" stroke="black" points="184.147,-103.602 101.853,-103.602 "></polyline>
<path fill="none" stroke="black" d="M101.853,-103.602C95.8526,-103.602 89.8526,-97.6019 89.8526,-91.6019"></path>
<polyline fill="none" stroke="black" points="89.8526,-91.6019 89.8526,-74.3981 "></polyline>
<path fill="none" stroke="black" d="M89.8526,-74.3981C89.8526,-68.3981 95.8526,-62.3981 101.853,-62.3981"></path>
<polyline fill="none" stroke="black" points="101.853,-62.3981 184.147,-62.3981 "></polyline>
<path fill="none" stroke="black" d="M184.147,-62.3981C190.147,-62.3981 196.147,-68.3981 196.147,-74.3981"></path>
<polyline fill="none" stroke="black" points="196.147,-74.3981 196.147,-91.6019 "></polyline>
<path fill="none" stroke="black" d="M196.147,-91.6019C196.147,-97.6019 190.147,-103.602 184.147,-103.602"></path>
<text text-anchor="middle" x="143" y="-87.2" font-family="Times,serif" font-size="14.00">IfStatement:exit</text>
<text text-anchor="middle" x="143" y="-70.4" font-family="Times,serif" font-size="14.00">Program:exit</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_4</title>
<path fill="none" stroke="black" d="M97.0372,-140.244C104.852,-130.681 113.137,-120.543 120.488,-111.547"></path>
<polygon fill="black" stroke="black" points="123.32,-113.613 126.938,-103.655 117.899,-109.184 123.32,-113.613"></polygon>
</g>
<g id="edge8" class="edge"><title>s1_4-&gt;final</title>
<path fill="none" stroke="black" d="M143,-62.3316C143,-54.2587 143,-44.8663 143,-36.5198"></path>
<polygon fill="black" stroke="black" points="146.5,-36.3487 143,-26.3488 139.5,-36.3488 146.5,-36.3487"></polygon>
</g>
<g id="edge7" class="edge"><title>s1_3-&gt;s1_4</title>
<path fill="none" stroke="black" d="M188.963,-140.244C181.148,-130.681 172.863,-120.543 165.512,-111.547"></path>
<polygon fill="black" stroke="black" points="168.101,-109.184 159.062,-103.655 162.68,-113.613 168.101,-109.184"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -0,0 +1,279 @@
<?xml version="1.0"?>
<svg width="347pt" height="802pt" viewBox="0.00 0.00 347.00 802.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 798)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="121" cy="-785" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="164.156,-740 77.8443,-740 65.8443,-728 65.8443,-660 77.8443,-648 164.156,-648 176.156,-660 176.156,-728 164.156,-740"></polygon>
<path fill="white" stroke="white" d="M77.8443,-740C71.8443,-740 65.8443,-734 65.8443,-728"></path>
<path fill="white" stroke="white" d="M65.8443,-660C65.8443,-654 71.8443,-648 77.8443,-648"></path>
<path fill="white" stroke="white" d="M164.156,-648C170.156,-648 176.156,-654 176.156,-660"></path>
<path fill="white" stroke="white" d="M176.156,-728C176.156,-734 170.156,-740 164.156,-740"></path>
<polyline fill="none" stroke="black" points="164.156,-740 77.8443,-740 "></polyline>
<path fill="none" stroke="black" d="M77.8443,-740C71.8443,-740 65.8443,-734 65.8443,-728"></path>
<polyline fill="none" stroke="black" points="65.8443,-728 65.8443,-660 "></polyline>
<path fill="none" stroke="black" d="M65.8443,-660C65.8443,-654 71.8443,-648 77.8443,-648"></path>
<polyline fill="none" stroke="black" points="77.8443,-648 164.156,-648 "></polyline>
<path fill="none" stroke="black" d="M164.156,-648C170.156,-648 176.156,-654 176.156,-660"></path>
<polyline fill="none" stroke="black" points="176.156,-660 176.156,-728 "></polyline>
<path fill="none" stroke="black" d="M176.156,-728C176.156,-734 170.156,-740 164.156,-740"></path>
<text text-anchor="middle" x="121" y="-723.4" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="121" y="-706.6" font-family="Times,serif" font-size="14.00">SwitchStatement</text>
<text text-anchor="middle" x="121" y="-689.8" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
<text text-anchor="middle" x="121" y="-673" font-family="Times,serif" font-size="14.00">SwitchCase</text>
<text text-anchor="middle" x="121" y="-656.2" font-family="Times,serif" font-size="14.00">Literal (0)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M121,-775.787C121,-769.525 121,-760.299 121,-750.297"></path>
<polygon fill="black" stroke="black" points="124.5,-750.119 121,-740.119 117.5,-750.119 124.5,-750.119"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="162" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="162" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="122.147,-533.7 11.8526,-533.7 -0.147372,-521.7 -0.147372,-470.3 11.8526,-458.3 122.147,-458.3 134.147,-470.3 134.147,-521.7 122.147,-533.7"></polygon>
<path fill="white" stroke="white" d="M11.8526,-533.7C5.85263,-533.7 -0.147372,-527.7 -0.147372,-521.7"></path>
<path fill="white" stroke="white" d="M-0.147372,-470.3C-0.147372,-464.3 5.85263,-458.3 11.8526,-458.3"></path>
<path fill="white" stroke="white" d="M122.147,-458.3C128.147,-458.3 134.147,-464.3 134.147,-470.3"></path>
<path fill="white" stroke="white" d="M134.147,-521.7C134.147,-527.7 128.147,-533.7 122.147,-533.7"></path>
<polyline fill="none" stroke="black" points="122.147,-533.7 11.8526,-533.7 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-533.7C5.85263,-533.7 -0.147372,-527.7 -0.147372,-521.7"></path>
<polyline fill="none" stroke="black" points="-0.147372,-521.7 -0.147372,-470.3 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-470.3C-0.147372,-464.3 5.85263,-458.3 11.8526,-458.3"></path>
<polyline fill="none" stroke="black" points="11.8526,-458.3 122.147,-458.3 "></polyline>
<path fill="none" stroke="black" d="M122.147,-458.3C128.147,-458.3 134.147,-464.3 134.147,-470.3"></path>
<polyline fill="none" stroke="black" points="134.147,-470.3 134.147,-521.7 "></polyline>
<path fill="none" stroke="black" d="M134.147,-521.7C134.147,-527.7 128.147,-533.7 122.147,-533.7"></path>
<text text-anchor="middle" x="67" y="-517" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-500.2" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-483.4" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="67" y="-466.6" font-family="Times,serif" font-size="14.00">BreakStatement</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M108.476,-647.541C99.8727,-616.316 88.4862,-574.987 79.8204,-543.533"></path>
<polygon fill="black" stroke="black" points="83.14,-542.405 77.1095,-533.694 76.3914,-544.264 83.14,-542.405"></polygon>
</g>
<g id="node9" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="191.072,-611.602 132.928,-611.602 120.928,-599.602 120.928,-582.398 132.928,-570.398 191.072,-570.398 203.072,-582.398 203.072,-599.602 191.072,-611.602"></polygon>
<path fill="white" stroke="white" d="M132.928,-611.602C126.928,-611.602 120.928,-605.602 120.928,-599.602"></path>
<path fill="white" stroke="white" d="M120.928,-582.398C120.928,-576.398 126.928,-570.398 132.928,-570.398"></path>
<path fill="white" stroke="white" d="M191.072,-570.398C197.072,-570.398 203.072,-576.398 203.072,-582.398"></path>
<path fill="white" stroke="white" d="M203.072,-599.602C203.072,-605.602 197.072,-611.602 191.072,-611.602"></path>
<polyline fill="none" stroke="black" points="191.072,-611.602 132.928,-611.602 "></polyline>
<path fill="none" stroke="black" d="M132.928,-611.602C126.928,-611.602 120.928,-605.602 120.928,-599.602"></path>
<polyline fill="none" stroke="black" points="120.928,-599.602 120.928,-582.398 "></polyline>
<path fill="none" stroke="black" d="M120.928,-582.398C120.928,-576.398 126.928,-570.398 132.928,-570.398"></path>
<polyline fill="none" stroke="black" points="132.928,-570.398 191.072,-570.398 "></polyline>
<path fill="none" stroke="black" d="M191.072,-570.398C197.072,-570.398 203.072,-576.398 203.072,-582.398"></path>
<polyline fill="none" stroke="black" points="203.072,-582.398 203.072,-599.602 "></polyline>
<path fill="none" stroke="black" d="M203.072,-599.602C203.072,-605.602 197.072,-611.602 191.072,-611.602"></path>
<text text-anchor="middle" x="162" y="-595.2" font-family="Times,serif" font-size="14.00">SwitchCase</text>
<text text-anchor="middle" x="162" y="-578.4" font-family="Times,serif" font-size="14.00">Literal (1)</text>
</g>
<g id="edge7" class="edge"><title>s1_1-&gt;s1_4</title>
<path fill="none" stroke="black" d="M139.341,-647.817C143.019,-638.757 146.791,-629.466 150.176,-621.128"></path>
<polygon fill="black" stroke="black" points="153.424,-622.431 153.943,-611.849 146.938,-619.798 153.424,-622.431"></polygon>
</g>
<g id="node8" class="node"><title>s1_14</title>
<polygon fill="white" stroke="white" points="217.321,-103.602 106.679,-103.602 94.6789,-91.6019 94.6789,-74.3981 106.679,-62.3981 217.321,-62.3981 229.321,-74.3981 229.321,-91.6019 217.321,-103.602"></polygon>
<path fill="white" stroke="white" d="M106.679,-103.602C100.679,-103.602 94.6789,-97.6019 94.6789,-91.6019"></path>
<path fill="white" stroke="white" d="M94.6789,-74.3981C94.6789,-68.3981 100.679,-62.3981 106.679,-62.3981"></path>
<path fill="white" stroke="white" d="M217.321,-62.3981C223.321,-62.3981 229.321,-68.3981 229.321,-74.3981"></path>
<path fill="white" stroke="white" d="M229.321,-91.6019C229.321,-97.6019 223.321,-103.602 217.321,-103.602"></path>
<polyline fill="none" stroke="black" points="217.321,-103.602 106.679,-103.602 "></polyline>
<path fill="none" stroke="black" d="M106.679,-103.602C100.679,-103.602 94.6789,-97.6019 94.6789,-91.6019"></path>
<polyline fill="none" stroke="black" points="94.6789,-91.6019 94.6789,-74.3981 "></polyline>
<path fill="none" stroke="black" d="M94.6789,-74.3981C94.6789,-68.3981 100.679,-62.3981 106.679,-62.3981"></path>
<polyline fill="none" stroke="black" points="106.679,-62.3981 217.321,-62.3981 "></polyline>
<path fill="none" stroke="black" d="M217.321,-62.3981C223.321,-62.3981 229.321,-68.3981 229.321,-74.3981"></path>
<polyline fill="none" stroke="black" points="229.321,-74.3981 229.321,-91.6019 "></polyline>
<path fill="none" stroke="black" d="M229.321,-91.6019C229.321,-97.6019 223.321,-103.602 217.321,-103.602"></path>
<text text-anchor="middle" x="162" y="-87.2" font-family="Times,serif" font-size="14.00">SwitchStatement:exit</text>
<text text-anchor="middle" x="162" y="-70.4" font-family="Times,serif" font-size="14.00">Program:exit</text>
</g>
<g id="edge11" class="edge"><title>s1_2-&gt;s1_14</title>
<path fill="none" stroke="black" d="M65.9609,-458.127C65.4872,-409.946 67.6815,-323.315 86,-252 99.1928,-200.639 127.133,-145.406 145.212,-112.816"></path>
<polygon fill="black" stroke="black" points="148.402,-114.284 150.254,-103.852 142.301,-110.852 148.402,-114.284"></polygon>
</g>
<g id="node5" class="node"><title>s1_7</title>
<polygon fill="white" stroke="white" points="217.147,-422.401 106.853,-422.401 94.8526,-410.401 94.8526,-375.599 106.853,-363.599 217.147,-363.599 229.147,-375.599 229.147,-410.401 217.147,-422.401"></polygon>
<path fill="white" stroke="white" d="M106.853,-422.401C100.853,-422.401 94.8526,-416.401 94.8526,-410.401"></path>
<path fill="white" stroke="white" d="M94.8526,-375.599C94.8526,-369.599 100.853,-363.599 106.853,-363.599"></path>
<path fill="white" stroke="white" d="M217.147,-363.599C223.147,-363.599 229.147,-369.599 229.147,-375.599"></path>
<path fill="white" stroke="white" d="M229.147,-410.401C229.147,-416.401 223.147,-422.401 217.147,-422.401"></path>
<polyline fill="none" stroke="black" points="217.147,-422.401 106.853,-422.401 "></polyline>
<path fill="none" stroke="black" d="M106.853,-422.401C100.853,-422.401 94.8526,-416.401 94.8526,-410.401"></path>
<polyline fill="none" stroke="black" points="94.8526,-410.401 94.8526,-375.599 "></polyline>
<path fill="none" stroke="black" d="M94.8526,-375.599C94.8526,-369.599 100.853,-363.599 106.853,-363.599"></path>
<polyline fill="none" stroke="black" points="106.853,-363.599 217.147,-363.599 "></polyline>
<path fill="none" stroke="black" d="M217.147,-363.599C223.147,-363.599 229.147,-369.599 229.147,-375.599"></path>
<polyline fill="none" stroke="black" points="229.147,-375.599 229.147,-410.401 "></polyline>
<path fill="none" stroke="black" d="M229.147,-410.401C229.147,-416.401 223.147,-422.401 217.147,-422.401"></path>
<text text-anchor="middle" x="162" y="-405.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="162" y="-388.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="162" y="-372" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="node6" class="node"><title>s1_9</title>
<polygon fill="white" stroke="white" points="217.147,-327.7 106.853,-327.7 94.8526,-315.7 94.8526,-264.3 106.853,-252.3 217.147,-252.3 229.147,-264.3 229.147,-315.7 217.147,-327.7"></polygon>
<path fill="white" stroke="white" d="M106.853,-327.7C100.853,-327.7 94.8526,-321.7 94.8526,-315.7"></path>
<path fill="white" stroke="white" d="M94.8526,-264.3C94.8526,-258.3 100.853,-252.3 106.853,-252.3"></path>
<path fill="white" stroke="white" d="M217.147,-252.3C223.147,-252.3 229.147,-258.3 229.147,-264.3"></path>
<path fill="white" stroke="white" d="M229.147,-315.7C229.147,-321.7 223.147,-327.7 217.147,-327.7"></path>
<polyline fill="none" stroke="black" points="217.147,-327.7 106.853,-327.7 "></polyline>
<path fill="none" stroke="black" d="M106.853,-327.7C100.853,-327.7 94.8526,-321.7 94.8526,-315.7"></path>
<polyline fill="none" stroke="black" points="94.8526,-315.7 94.8526,-264.3 "></polyline>
<path fill="none" stroke="black" d="M94.8526,-264.3C94.8526,-258.3 100.853,-252.3 106.853,-252.3"></path>
<polyline fill="none" stroke="black" points="106.853,-252.3 217.147,-252.3 "></polyline>
<path fill="none" stroke="black" d="M217.147,-252.3C223.147,-252.3 229.147,-258.3 229.147,-264.3"></path>
<polyline fill="none" stroke="black" points="229.147,-264.3 229.147,-315.7 "></polyline>
<path fill="none" stroke="black" d="M229.147,-315.7C229.147,-321.7 223.147,-327.7 217.147,-327.7"></path>
<text text-anchor="middle" x="162" y="-311" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="162" y="-294.2" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="162" y="-277.4" font-family="Times,serif" font-size="14.00">Identifier (hoge)</text>
<text text-anchor="middle" x="162" y="-260.6" font-family="Times,serif" font-size="14.00">BreakStatement</text>
</g>
<g id="edge5" class="edge"><title>s1_7-&gt;s1_9</title>
<path fill="none" stroke="black" d="M162,-363.597C162,-355.629 162,-346.747 162,-338.005"></path>
<polygon fill="black" stroke="black" points="165.5,-337.871 162,-327.871 158.5,-337.871 165.5,-337.871"></polygon>
</g>
<g id="edge13" class="edge"><title>s1_9-&gt;s1_14</title>
<path fill="none" stroke="black" d="M162,-252.35C162,-212.728 162,-150.341 162,-113.673"></path>
<polygon fill="black" stroke="black" points="165.5,-113.613 162,-103.613 158.5,-113.613 165.5,-113.613"></polygon>
</g>
<g id="node7" class="node"><title>s1_12</title>
<polygon fill="white" stroke="white" points="327.147,-215.7 216.853,-215.7 204.853,-203.7 204.853,-152.3 216.853,-140.3 327.147,-140.3 339.147,-152.3 339.147,-203.7 327.147,-215.7"></polygon>
<path fill="white" stroke="white" d="M216.853,-215.7C210.853,-215.7 204.853,-209.7 204.853,-203.7"></path>
<path fill="white" stroke="white" d="M204.853,-152.3C204.853,-146.3 210.853,-140.3 216.853,-140.3"></path>
<path fill="white" stroke="white" d="M327.147,-140.3C333.147,-140.3 339.147,-146.3 339.147,-152.3"></path>
<path fill="white" stroke="white" d="M339.147,-203.7C339.147,-209.7 333.147,-215.7 327.147,-215.7"></path>
<polyline fill="none" stroke="black" points="327.147,-215.7 216.853,-215.7 "></polyline>
<path fill="none" stroke="black" d="M216.853,-215.7C210.853,-215.7 204.853,-209.7 204.853,-203.7"></path>
<polyline fill="none" stroke="black" points="204.853,-203.7 204.853,-152.3 "></polyline>
<path fill="none" stroke="black" d="M204.853,-152.3C204.853,-146.3 210.853,-140.3 216.853,-140.3"></path>
<polyline fill="none" stroke="black" points="216.853,-140.3 327.147,-140.3 "></polyline>
<path fill="none" stroke="black" d="M327.147,-140.3C333.147,-140.3 339.147,-146.3 339.147,-152.3"></path>
<polyline fill="none" stroke="black" points="339.147,-152.3 339.147,-203.7 "></polyline>
<path fill="none" stroke="black" d="M339.147,-203.7C339.147,-209.7 333.147,-215.7 327.147,-215.7"></path>
<text text-anchor="middle" x="272" y="-199" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="272" y="-182.2" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="272" y="-165.4" font-family="Times,serif" font-size="14.00">Identifier (fuga)</text>
<text text-anchor="middle" x="272" y="-148.6" font-family="Times,serif" font-size="14.00">BreakStatement</text>
</g>
<g id="edge15" class="edge"><title>s1_12-&gt;s1_14</title>
<path fill="none" stroke="black" d="M228.525,-140.244C216.638,-130.194 203.998,-119.507 192.965,-110.179"></path>
<polygon fill="black" stroke="black" points="195.145,-107.439 185.248,-103.655 190.625,-112.785 195.145,-107.439"></polygon>
</g>
<g id="edge25" class="edge"><title>s1_14-&gt;final</title>
<path fill="none" stroke="black" d="M162,-62.3316C162,-54.2587 162,-44.8663 162,-36.5198"></path>
<polygon fill="black" stroke="black" points="165.5,-36.3487 162,-26.3488 158.5,-36.3488 165.5,-36.3487"></polygon>
</g>
<g id="edge17" class="edge"><title>s1_4-&gt;s1_7</title>
<path fill="none" stroke="black" d="M162,-570.128C162,-537.987 162,-474.03 162,-432.674"></path>
<polygon fill="black" stroke="black" points="165.5,-432.424 162,-422.424 158.5,-432.424 165.5,-432.424"></polygon>
</g>
<g id="node10" class="node"><title>s1_6</title>
<polygon fill="white" stroke="white" points="260.072,-516.602 201.928,-516.602 189.928,-504.602 189.928,-487.398 201.928,-475.398 260.072,-475.398 272.072,-487.398 272.072,-504.602 260.072,-516.602"></polygon>
<path fill="white" stroke="white" d="M201.928,-516.602C195.928,-516.602 189.928,-510.602 189.928,-504.602"></path>
<path fill="white" stroke="white" d="M189.928,-487.398C189.928,-481.398 195.928,-475.398 201.928,-475.398"></path>
<path fill="white" stroke="white" d="M260.072,-475.398C266.072,-475.398 272.072,-481.398 272.072,-487.398"></path>
<path fill="white" stroke="white" d="M272.072,-504.602C272.072,-510.602 266.072,-516.602 260.072,-516.602"></path>
<polyline fill="none" stroke="black" points="260.072,-516.602 201.928,-516.602 "></polyline>
<path fill="none" stroke="black" d="M201.928,-516.602C195.928,-516.602 189.928,-510.602 189.928,-504.602"></path>
<polyline fill="none" stroke="black" points="189.928,-504.602 189.928,-487.398 "></polyline>
<path fill="none" stroke="black" d="M189.928,-487.398C189.928,-481.398 195.928,-475.398 201.928,-475.398"></path>
<polyline fill="none" stroke="black" points="201.928,-475.398 260.072,-475.398 "></polyline>
<path fill="none" stroke="black" d="M260.072,-475.398C266.072,-475.398 272.072,-481.398 272.072,-487.398"></path>
<polyline fill="none" stroke="black" points="272.072,-487.398 272.072,-504.602 "></polyline>
<path fill="none" stroke="black" d="M272.072,-504.602C272.072,-510.602 266.072,-516.602 260.072,-516.602"></path>
<text text-anchor="middle" x="231" y="-500.2" font-family="Times,serif" font-size="14.00">SwitchCase</text>
<text text-anchor="middle" x="231" y="-483.4" font-family="Times,serif" font-size="14.00">Literal (2)</text>
</g>
<g id="edge8" class="edge"><title>s1_4-&gt;s1_6</title>
<path fill="none" stroke="black" d="M176.633,-570.277C186.422,-557.084 199.447,-539.528 210.294,-524.908"></path>
<polygon fill="black" stroke="black" points="213.24,-526.811 216.388,-516.694 207.619,-522.64 213.24,-526.811"></polygon>
</g>
<g id="edge9" class="edge"><title>s1_6-&gt;s1_7</title>
<path fill="none" stroke="black" d="M217.368,-475.046C208.766,-462.455 197.392,-445.806 187.191,-430.874"></path>
<polygon fill="black" stroke="black" points="189.882,-428.608 181.351,-422.325 184.102,-432.557 189.882,-428.608"></polygon>
</g>
<g id="node11" class="node"><title>s1_8</title>
<polygon fill="white" stroke="white" points="317.072,-413.602 258.928,-413.602 246.928,-401.602 246.928,-384.398 258.928,-372.398 317.072,-372.398 329.072,-384.398 329.072,-401.602 317.072,-413.602"></polygon>
<path fill="white" stroke="white" d="M258.928,-413.602C252.928,-413.602 246.928,-407.602 246.928,-401.602"></path>
<path fill="white" stroke="white" d="M246.928,-384.398C246.928,-378.398 252.928,-372.398 258.928,-372.398"></path>
<path fill="white" stroke="white" d="M317.072,-372.398C323.072,-372.398 329.072,-378.398 329.072,-384.398"></path>
<path fill="white" stroke="white" d="M329.072,-401.602C329.072,-407.602 323.072,-413.602 317.072,-413.602"></path>
<polyline fill="none" stroke="black" points="317.072,-413.602 258.928,-413.602 "></polyline>
<path fill="none" stroke="black" d="M258.928,-413.602C252.928,-413.602 246.928,-407.602 246.928,-401.602"></path>
<polyline fill="none" stroke="black" points="246.928,-401.602 246.928,-384.398 "></polyline>
<path fill="none" stroke="black" d="M246.928,-384.398C246.928,-378.398 252.928,-372.398 258.928,-372.398"></path>
<polyline fill="none" stroke="black" points="258.928,-372.398 317.072,-372.398 "></polyline>
<path fill="none" stroke="black" d="M317.072,-372.398C323.072,-372.398 329.072,-378.398 329.072,-384.398"></path>
<polyline fill="none" stroke="black" points="329.072,-384.398 329.072,-401.602 "></polyline>
<path fill="none" stroke="black" d="M329.072,-401.602C329.072,-407.602 323.072,-413.602 317.072,-413.602"></path>
<text text-anchor="middle" x="288" y="-397.2" font-family="Times,serif" font-size="14.00">SwitchCase</text>
<text text-anchor="middle" x="288" y="-380.4" font-family="Times,serif" font-size="14.00">Literal (3)</text>
</g>
<g id="edge19" class="edge"><title>s1_6-&gt;s1_8</title>
<path fill="none" stroke="black" d="M242.261,-475.046C250.693,-460.106 262.349,-439.452 271.784,-422.734"></path>
<polygon fill="black" stroke="black" points="274.895,-424.342 276.762,-413.913 268.799,-420.902 274.895,-424.342"></polygon>
</g>
<g id="edge20" class="edge"><title>s1_8-&gt;s1_9</title>
<path fill="none" stroke="black" d="M263.407,-372.286C249.805,-361.383 232.341,-347.384 215.751,-334.086"></path>
<polygon fill="black" stroke="black" points="217.69,-331.155 207.698,-327.631 213.312,-336.617 217.69,-331.155"></polygon>
</g>
<g id="node12" class="node"><title>s1_11</title>
<polygon fill="white" stroke="white" points="317.072,-308 258.928,-308 246.928,-296 246.928,-284 258.928,-272 317.072,-272 329.072,-284 329.072,-296 317.072,-308"></polygon>
<path fill="white" stroke="white" d="M258.928,-308C252.928,-308 246.928,-302 246.928,-296"></path>
<path fill="white" stroke="white" d="M246.928,-284C246.928,-278 252.928,-272 258.928,-272"></path>
<path fill="white" stroke="white" d="M317.072,-272C323.072,-272 329.072,-278 329.072,-284"></path>
<path fill="white" stroke="white" d="M329.072,-296C329.072,-302 323.072,-308 317.072,-308"></path>
<polyline fill="none" stroke="black" points="317.072,-308 258.928,-308 "></polyline>
<path fill="none" stroke="black" d="M258.928,-308C252.928,-308 246.928,-302 246.928,-296"></path>
<polyline fill="none" stroke="black" points="246.928,-296 246.928,-284 "></polyline>
<path fill="none" stroke="black" d="M246.928,-284C246.928,-278 252.928,-272 258.928,-272"></path>
<polyline fill="none" stroke="black" points="258.928,-272 317.072,-272 "></polyline>
<path fill="none" stroke="black" d="M317.072,-272C323.072,-272 329.072,-278 329.072,-284"></path>
<polyline fill="none" stroke="black" points="329.072,-284 329.072,-296 "></polyline>
<path fill="none" stroke="black" d="M329.072,-296C329.072,-302 323.072,-308 317.072,-308"></path>
<text text-anchor="middle" x="288" y="-285.8" font-family="Times,serif" font-size="14.00">SwitchCase</text>
</g>
<g id="edge22" class="edge"><title>s1_8-&gt;s1_11</title>
<path fill="none" stroke="black" d="M288,-372.046C288,-356.766 288,-335.511 288,-318.601"></path>
<polygon fill="black" stroke="black" points="291.5,-318.223 288,-308.223 284.5,-318.223 291.5,-318.223"></polygon>
</g>
<g id="edge23" class="edge"><title>s1_11-&gt;s1_12</title>
<path fill="none" stroke="black" d="M285.5,-271.813C283.695,-259.403 281.166,-242.015 278.784,-225.64"></path>
<polygon fill="black" stroke="black" points="282.231,-225.02 277.328,-215.628 275.304,-226.028 282.231,-225.02"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,232 @@
<?xml version="1.0"?>
<svg width="337pt" height="690pt" viewBox="0.00 0.00 337.00 690.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 686)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="121" cy="-673" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="164.156,-628 77.8443,-628 65.8443,-616 65.8443,-548 77.8443,-536 164.156,-536 176.156,-548 176.156,-616 164.156,-628"></polygon>
<path fill="white" stroke="white" d="M77.8443,-628C71.8443,-628 65.8443,-622 65.8443,-616"></path>
<path fill="white" stroke="white" d="M65.8443,-548C65.8443,-542 71.8443,-536 77.8443,-536"></path>
<path fill="white" stroke="white" d="M164.156,-536C170.156,-536 176.156,-542 176.156,-548"></path>
<path fill="white" stroke="white" d="M176.156,-616C176.156,-622 170.156,-628 164.156,-628"></path>
<polyline fill="none" stroke="black" points="164.156,-628 77.8443,-628 "></polyline>
<path fill="none" stroke="black" d="M77.8443,-628C71.8443,-628 65.8443,-622 65.8443,-616"></path>
<polyline fill="none" stroke="black" points="65.8443,-616 65.8443,-548 "></polyline>
<path fill="none" stroke="black" d="M65.8443,-548C65.8443,-542 71.8443,-536 77.8443,-536"></path>
<polyline fill="none" stroke="black" points="77.8443,-536 164.156,-536 "></polyline>
<path fill="none" stroke="black" d="M164.156,-536C170.156,-536 176.156,-542 176.156,-548"></path>
<polyline fill="none" stroke="black" points="176.156,-548 176.156,-616 "></polyline>
<path fill="none" stroke="black" d="M176.156,-616C176.156,-622 170.156,-628 164.156,-628"></path>
<text text-anchor="middle" x="121" y="-611.4" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="121" y="-594.6" font-family="Times,serif" font-size="14.00">SwitchStatement</text>
<text text-anchor="middle" x="121" y="-577.8" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
<text text-anchor="middle" x="121" y="-561" font-family="Times,serif" font-size="14.00">SwitchCase</text>
<text text-anchor="middle" x="121" y="-544.2" font-family="Times,serif" font-size="14.00">Literal (0)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M121,-663.787C121,-657.525 121,-648.299 121,-638.297"></path>
<polygon fill="black" stroke="black" points="124.5,-638.119 121,-628.119 117.5,-638.119 124.5,-638.119"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="170" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="170" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="122.147,-421.7 11.8526,-421.7 -0.147372,-409.7 -0.147372,-358.3 11.8526,-346.3 122.147,-346.3 134.147,-358.3 134.147,-409.7 122.147,-421.7"></polygon>
<path fill="white" stroke="white" d="M11.8526,-421.7C5.85263,-421.7 -0.147372,-415.7 -0.147372,-409.7"></path>
<path fill="white" stroke="white" d="M-0.147372,-358.3C-0.147372,-352.3 5.85263,-346.3 11.8526,-346.3"></path>
<path fill="white" stroke="white" d="M122.147,-346.3C128.147,-346.3 134.147,-352.3 134.147,-358.3"></path>
<path fill="white" stroke="white" d="M134.147,-409.7C134.147,-415.7 128.147,-421.7 122.147,-421.7"></path>
<polyline fill="none" stroke="black" points="122.147,-421.7 11.8526,-421.7 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-421.7C5.85263,-421.7 -0.147372,-415.7 -0.147372,-409.7"></path>
<polyline fill="none" stroke="black" points="-0.147372,-409.7 -0.147372,-358.3 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-358.3C-0.147372,-352.3 5.85263,-346.3 11.8526,-346.3"></path>
<polyline fill="none" stroke="black" points="11.8526,-346.3 122.147,-346.3 "></polyline>
<path fill="none" stroke="black" d="M122.147,-346.3C128.147,-346.3 134.147,-352.3 134.147,-358.3"></path>
<polyline fill="none" stroke="black" points="134.147,-358.3 134.147,-409.7 "></polyline>
<path fill="none" stroke="black" d="M134.147,-409.7C134.147,-415.7 128.147,-421.7 122.147,-421.7"></path>
<text text-anchor="middle" x="67" y="-405" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-388.2" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-371.4" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="67" y="-354.6" font-family="Times,serif" font-size="14.00">BreakStatement</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M108.476,-535.541C99.8727,-504.316 88.4862,-462.987 79.8204,-431.533"></path>
<polygon fill="black" stroke="black" points="83.14,-430.405 77.1095,-421.694 76.3914,-432.264 83.14,-430.405"></polygon>
</g>
<g id="node8" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="191.072,-499.602 132.928,-499.602 120.928,-487.602 120.928,-470.398 132.928,-458.398 191.072,-458.398 203.072,-470.398 203.072,-487.602 191.072,-499.602"></polygon>
<path fill="white" stroke="white" d="M132.928,-499.602C126.928,-499.602 120.928,-493.602 120.928,-487.602"></path>
<path fill="white" stroke="white" d="M120.928,-470.398C120.928,-464.398 126.928,-458.398 132.928,-458.398"></path>
<path fill="white" stroke="white" d="M191.072,-458.398C197.072,-458.398 203.072,-464.398 203.072,-470.398"></path>
<path fill="white" stroke="white" d="M203.072,-487.602C203.072,-493.602 197.072,-499.602 191.072,-499.602"></path>
<polyline fill="none" stroke="black" points="191.072,-499.602 132.928,-499.602 "></polyline>
<path fill="none" stroke="black" d="M132.928,-499.602C126.928,-499.602 120.928,-493.602 120.928,-487.602"></path>
<polyline fill="none" stroke="black" points="120.928,-487.602 120.928,-470.398 "></polyline>
<path fill="none" stroke="black" d="M120.928,-470.398C120.928,-464.398 126.928,-458.398 132.928,-458.398"></path>
<polyline fill="none" stroke="black" points="132.928,-458.398 191.072,-458.398 "></polyline>
<path fill="none" stroke="black" d="M191.072,-458.398C197.072,-458.398 203.072,-464.398 203.072,-470.398"></path>
<polyline fill="none" stroke="black" points="203.072,-470.398 203.072,-487.602 "></polyline>
<path fill="none" stroke="black" d="M203.072,-487.602C203.072,-493.602 197.072,-499.602 191.072,-499.602"></path>
<text text-anchor="middle" x="162" y="-483.2" font-family="Times,serif" font-size="14.00">SwitchCase</text>
<text text-anchor="middle" x="162" y="-466.4" font-family="Times,serif" font-size="14.00">Literal (1)</text>
</g>
<g id="edge7" class="edge"><title>s1_1-&gt;s1_4</title>
<path fill="none" stroke="black" d="M139.341,-535.817C143.019,-526.757 146.791,-517.466 150.176,-509.128"></path>
<polygon fill="black" stroke="black" points="153.424,-510.431 153.943,-499.849 146.938,-507.798 153.424,-510.431"></polygon>
</g>
<g id="node7" class="node"><title>s1_11</title>
<polygon fill="white" stroke="white" points="225.321,-103.602 114.679,-103.602 102.679,-91.6019 102.679,-74.3981 114.679,-62.3981 225.321,-62.3981 237.321,-74.3981 237.321,-91.6019 225.321,-103.602"></polygon>
<path fill="white" stroke="white" d="M114.679,-103.602C108.679,-103.602 102.679,-97.6019 102.679,-91.6019"></path>
<path fill="white" stroke="white" d="M102.679,-74.3981C102.679,-68.3981 108.679,-62.3981 114.679,-62.3981"></path>
<path fill="white" stroke="white" d="M225.321,-62.3981C231.321,-62.3981 237.321,-68.3981 237.321,-74.3981"></path>
<path fill="white" stroke="white" d="M237.321,-91.6019C237.321,-97.6019 231.321,-103.602 225.321,-103.602"></path>
<polyline fill="none" stroke="black" points="225.321,-103.602 114.679,-103.602 "></polyline>
<path fill="none" stroke="black" d="M114.679,-103.602C108.679,-103.602 102.679,-97.6019 102.679,-91.6019"></path>
<polyline fill="none" stroke="black" points="102.679,-91.6019 102.679,-74.3981 "></polyline>
<path fill="none" stroke="black" d="M102.679,-74.3981C102.679,-68.3981 108.679,-62.3981 114.679,-62.3981"></path>
<polyline fill="none" stroke="black" points="114.679,-62.3981 225.321,-62.3981 "></polyline>
<path fill="none" stroke="black" d="M225.321,-62.3981C231.321,-62.3981 237.321,-68.3981 237.321,-74.3981"></path>
<polyline fill="none" stroke="black" points="237.321,-74.3981 237.321,-91.6019 "></polyline>
<path fill="none" stroke="black" d="M237.321,-91.6019C237.321,-97.6019 231.321,-103.602 225.321,-103.602"></path>
<text text-anchor="middle" x="170" y="-87.2" font-family="Times,serif" font-size="14.00">SwitchStatement:exit</text>
<text text-anchor="middle" x="170" y="-70.4" font-family="Times,serif" font-size="14.00">Program:exit</text>
</g>
<g id="edge11" class="edge"><title>s1_2-&gt;s1_11</title>
<path fill="none" stroke="black" d="M62.3638,-346.027C57.9153,-295.816 56.5654,-204.896 94,-140 100.985,-127.891 111.753,-117.634 123.007,-109.339"></path>
<polygon fill="black" stroke="black" points="125.004,-112.213 131.24,-103.648 121.024,-106.455 125.004,-112.213"></polygon>
</g>
<g id="node5" class="node"><title>s1_7</title>
<polygon fill="white" stroke="white" points="217.147,-310.401 106.853,-310.401 94.8526,-298.401 94.8526,-263.599 106.853,-251.599 217.147,-251.599 229.147,-263.599 229.147,-298.401 217.147,-310.401"></polygon>
<path fill="white" stroke="white" d="M106.853,-310.401C100.853,-310.401 94.8526,-304.401 94.8526,-298.401"></path>
<path fill="white" stroke="white" d="M94.8526,-263.599C94.8526,-257.599 100.853,-251.599 106.853,-251.599"></path>
<path fill="white" stroke="white" d="M217.147,-251.599C223.147,-251.599 229.147,-257.599 229.147,-263.599"></path>
<path fill="white" stroke="white" d="M229.147,-298.401C229.147,-304.401 223.147,-310.401 217.147,-310.401"></path>
<polyline fill="none" stroke="black" points="217.147,-310.401 106.853,-310.401 "></polyline>
<path fill="none" stroke="black" d="M106.853,-310.401C100.853,-310.401 94.8526,-304.401 94.8526,-298.401"></path>
<polyline fill="none" stroke="black" points="94.8526,-298.401 94.8526,-263.599 "></polyline>
<path fill="none" stroke="black" d="M94.8526,-263.599C94.8526,-257.599 100.853,-251.599 106.853,-251.599"></path>
<polyline fill="none" stroke="black" points="106.853,-251.599 217.147,-251.599 "></polyline>
<path fill="none" stroke="black" d="M217.147,-251.599C223.147,-251.599 229.147,-257.599 229.147,-263.599"></path>
<polyline fill="none" stroke="black" points="229.147,-263.599 229.147,-298.401 "></polyline>
<path fill="none" stroke="black" d="M229.147,-298.401C229.147,-304.401 223.147,-310.401 217.147,-310.401"></path>
<text text-anchor="middle" x="162" y="-293.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="162" y="-276.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="162" y="-260" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="node6" class="node"><title>s1_9</title>
<polygon fill="white" stroke="white" points="225.147,-215.7 114.853,-215.7 102.853,-203.7 102.853,-152.3 114.853,-140.3 225.147,-140.3 237.147,-152.3 237.147,-203.7 225.147,-215.7"></polygon>
<path fill="white" stroke="white" d="M114.853,-215.7C108.853,-215.7 102.853,-209.7 102.853,-203.7"></path>
<path fill="white" stroke="white" d="M102.853,-152.3C102.853,-146.3 108.853,-140.3 114.853,-140.3"></path>
<path fill="white" stroke="white" d="M225.147,-140.3C231.147,-140.3 237.147,-146.3 237.147,-152.3"></path>
<path fill="white" stroke="white" d="M237.147,-203.7C237.147,-209.7 231.147,-215.7 225.147,-215.7"></path>
<polyline fill="none" stroke="black" points="225.147,-215.7 114.853,-215.7 "></polyline>
<path fill="none" stroke="black" d="M114.853,-215.7C108.853,-215.7 102.853,-209.7 102.853,-203.7"></path>
<polyline fill="none" stroke="black" points="102.853,-203.7 102.853,-152.3 "></polyline>
<path fill="none" stroke="black" d="M102.853,-152.3C102.853,-146.3 108.853,-140.3 114.853,-140.3"></path>
<polyline fill="none" stroke="black" points="114.853,-140.3 225.147,-140.3 "></polyline>
<path fill="none" stroke="black" d="M225.147,-140.3C231.147,-140.3 237.147,-146.3 237.147,-152.3"></path>
<polyline fill="none" stroke="black" points="237.147,-152.3 237.147,-203.7 "></polyline>
<path fill="none" stroke="black" d="M237.147,-203.7C237.147,-209.7 231.147,-215.7 225.147,-215.7"></path>
<text text-anchor="middle" x="170" y="-199" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="170" y="-182.2" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="170" y="-165.4" font-family="Times,serif" font-size="14.00">Identifier (hoge)</text>
<text text-anchor="middle" x="170" y="-148.6" font-family="Times,serif" font-size="14.00">BreakStatement</text>
</g>
<g id="edge5" class="edge"><title>s1_7-&gt;s1_9</title>
<path fill="none" stroke="black" d="M164.25,-251.597C164.881,-243.629 165.584,-234.747 166.277,-226.005"></path>
<polygon fill="black" stroke="black" points="169.779,-226.116 167.08,-215.871 162.801,-225.563 169.779,-226.116"></polygon>
</g>
<g id="edge13" class="edge"><title>s1_9-&gt;s1_11</title>
<path fill="none" stroke="black" d="M170,-140.244C170,-131.462 170,-122.195 170,-113.772"></path>
<polygon fill="black" stroke="black" points="173.5,-113.655 170,-103.655 166.5,-113.655 173.5,-113.655"></polygon>
</g>
<g id="edge21" class="edge"><title>s1_11-&gt;final</title>
<path fill="none" stroke="black" d="M170,-62.3316C170,-54.2587 170,-44.8663 170,-36.5198"></path>
<polygon fill="black" stroke="black" points="173.5,-36.3487 170,-26.3488 166.5,-36.3488 173.5,-36.3487"></polygon>
</g>
<g id="edge15" class="edge"><title>s1_4-&gt;s1_7</title>
<path fill="none" stroke="black" d="M162,-458.128C162,-425.987 162,-362.03 162,-320.674"></path>
<polygon fill="black" stroke="black" points="165.5,-320.424 162,-310.424 158.5,-320.424 165.5,-320.424"></polygon>
</g>
<g id="node9" class="node"><title>s1_6</title>
<polygon fill="white" stroke="white" points="260.072,-404.602 201.928,-404.602 189.928,-392.602 189.928,-375.398 201.928,-363.398 260.072,-363.398 272.072,-375.398 272.072,-392.602 260.072,-404.602"></polygon>
<path fill="white" stroke="white" d="M201.928,-404.602C195.928,-404.602 189.928,-398.602 189.928,-392.602"></path>
<path fill="white" stroke="white" d="M189.928,-375.398C189.928,-369.398 195.928,-363.398 201.928,-363.398"></path>
<path fill="white" stroke="white" d="M260.072,-363.398C266.072,-363.398 272.072,-369.398 272.072,-375.398"></path>
<path fill="white" stroke="white" d="M272.072,-392.602C272.072,-398.602 266.072,-404.602 260.072,-404.602"></path>
<polyline fill="none" stroke="black" points="260.072,-404.602 201.928,-404.602 "></polyline>
<path fill="none" stroke="black" d="M201.928,-404.602C195.928,-404.602 189.928,-398.602 189.928,-392.602"></path>
<polyline fill="none" stroke="black" points="189.928,-392.602 189.928,-375.398 "></polyline>
<path fill="none" stroke="black" d="M189.928,-375.398C189.928,-369.398 195.928,-363.398 201.928,-363.398"></path>
<polyline fill="none" stroke="black" points="201.928,-363.398 260.072,-363.398 "></polyline>
<path fill="none" stroke="black" d="M260.072,-363.398C266.072,-363.398 272.072,-369.398 272.072,-375.398"></path>
<polyline fill="none" stroke="black" points="272.072,-375.398 272.072,-392.602 "></polyline>
<path fill="none" stroke="black" d="M272.072,-392.602C272.072,-398.602 266.072,-404.602 260.072,-404.602"></path>
<text text-anchor="middle" x="231" y="-388.2" font-family="Times,serif" font-size="14.00">SwitchCase</text>
<text text-anchor="middle" x="231" y="-371.4" font-family="Times,serif" font-size="14.00">Literal (2)</text>
</g>
<g id="edge8" class="edge"><title>s1_4-&gt;s1_6</title>
<path fill="none" stroke="black" d="M176.633,-458.277C186.422,-445.084 199.447,-427.528 210.294,-412.908"></path>
<polygon fill="black" stroke="black" points="213.24,-414.811 216.388,-404.694 207.619,-410.64 213.24,-414.811"></polygon>
</g>
<g id="edge9" class="edge"><title>s1_6-&gt;s1_7</title>
<path fill="none" stroke="black" d="M217.368,-363.046C208.766,-350.455 197.392,-333.806 187.191,-318.874"></path>
<polygon fill="black" stroke="black" points="189.882,-316.608 181.351,-310.325 184.102,-320.557 189.882,-316.608"></polygon>
</g>
<g id="node10" class="node"><title>s1_8</title>
<polygon fill="white" stroke="white" points="317.072,-301.602 258.928,-301.602 246.928,-289.602 246.928,-272.398 258.928,-260.398 317.072,-260.398 329.072,-272.398 329.072,-289.602 317.072,-301.602"></polygon>
<path fill="white" stroke="white" d="M258.928,-301.602C252.928,-301.602 246.928,-295.602 246.928,-289.602"></path>
<path fill="white" stroke="white" d="M246.928,-272.398C246.928,-266.398 252.928,-260.398 258.928,-260.398"></path>
<path fill="white" stroke="white" d="M317.072,-260.398C323.072,-260.398 329.072,-266.398 329.072,-272.398"></path>
<path fill="white" stroke="white" d="M329.072,-289.602C329.072,-295.602 323.072,-301.602 317.072,-301.602"></path>
<polyline fill="none" stroke="black" points="317.072,-301.602 258.928,-301.602 "></polyline>
<path fill="none" stroke="black" d="M258.928,-301.602C252.928,-301.602 246.928,-295.602 246.928,-289.602"></path>
<polyline fill="none" stroke="black" points="246.928,-289.602 246.928,-272.398 "></polyline>
<path fill="none" stroke="black" d="M246.928,-272.398C246.928,-266.398 252.928,-260.398 258.928,-260.398"></path>
<polyline fill="none" stroke="black" points="258.928,-260.398 317.072,-260.398 "></polyline>
<path fill="none" stroke="black" d="M317.072,-260.398C323.072,-260.398 329.072,-266.398 329.072,-272.398"></path>
<polyline fill="none" stroke="black" points="329.072,-272.398 329.072,-289.602 "></polyline>
<path fill="none" stroke="black" d="M329.072,-289.602C329.072,-295.602 323.072,-301.602 317.072,-301.602"></path>
<text text-anchor="middle" x="288" y="-285.2" font-family="Times,serif" font-size="14.00">SwitchCase</text>
<text text-anchor="middle" x="288" y="-268.4" font-family="Times,serif" font-size="14.00">Literal (3)</text>
</g>
<g id="edge17" class="edge"><title>s1_6-&gt;s1_8</title>
<path fill="none" stroke="black" d="M242.261,-363.046C250.693,-348.106 262.349,-327.452 271.784,-310.734"></path>
<polygon fill="black" stroke="black" points="274.895,-312.342 276.762,-301.913 268.799,-308.902 274.895,-312.342"></polygon>
</g>
<g id="edge18" class="edge"><title>s1_8-&gt;s1_9</title>
<path fill="none" stroke="black" d="M264.968,-260.286C252.403,-249.531 236.318,-235.764 220.972,-222.628"></path>
<polygon fill="black" stroke="black" points="222.909,-219.68 213.036,-215.836 218.358,-224.998 222.909,-219.68"></polygon>
</g>
<g id="edge20" class="edge"><title>s1_8-&gt;s1_11</title>
<path fill="none" stroke="black" d="M286.047,-260.183C282.381,-231.387 272.302,-177.344 246,-140 237.722,-128.247 226.195,-117.974 214.617,-109.546"></path>
<polygon fill="black" stroke="black" points="216.439,-106.551 206.223,-103.741 212.457,-112.308 216.439,-106.551"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -0,0 +1,137 @@
<?xml version="1.0"?>
<svg width="237pt" height="652pt" viewBox="0.00 0.00 237.00 652.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 648)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="114" cy="-635" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="169.147,-589.3 58.8526,-589.3 46.8526,-577.3 46.8526,-492.7 58.8526,-480.7 169.147,-480.7 181.147,-492.7 181.147,-577.3 169.147,-589.3"></polygon>
<path fill="white" stroke="white" d="M58.8526,-589.3C52.8526,-589.3 46.8526,-583.3 46.8526,-577.3"></path>
<path fill="white" stroke="white" d="M46.8526,-492.7C46.8526,-486.7 52.8526,-480.7 58.8526,-480.7"></path>
<path fill="white" stroke="white" d="M169.147,-480.7C175.147,-480.7 181.147,-486.7 181.147,-492.7"></path>
<path fill="white" stroke="white" d="M181.147,-577.3C181.147,-583.3 175.147,-589.3 169.147,-589.3"></path>
<polyline fill="none" stroke="black" points="169.147,-589.3 58.8526,-589.3 "></polyline>
<path fill="none" stroke="black" d="M58.8526,-589.3C52.8526,-589.3 46.8526,-583.3 46.8526,-577.3"></path>
<polyline fill="none" stroke="black" points="46.8526,-577.3 46.8526,-492.7 "></polyline>
<path fill="none" stroke="black" d="M46.8526,-492.7C46.8526,-486.7 52.8526,-480.7 58.8526,-480.7"></path>
<polyline fill="none" stroke="black" points="58.8526,-480.7 169.147,-480.7 "></polyline>
<path fill="none" stroke="black" d="M169.147,-480.7C175.147,-480.7 181.147,-486.7 181.147,-492.7"></path>
<polyline fill="none" stroke="black" points="181.147,-492.7 181.147,-577.3 "></polyline>
<path fill="none" stroke="black" d="M181.147,-577.3C181.147,-583.3 175.147,-589.3 169.147,-589.3"></path>
<text text-anchor="middle" x="114" y="-572.8" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="114" y="-556" font-family="Times,serif" font-size="14.00">TryStatement</text>
<text text-anchor="middle" x="114" y="-539.2" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="114" y="-522.4" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="114" y="-505.6" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="114" y="-488.8" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M114,-625.98C114,-619.675 114,-610.238 114,-599.813"></path>
<polygon fill="black" stroke="black" points="117.5,-599.586 114,-589.586 110.5,-599.586 117.5,-599.586"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="114" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="114" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="217.147,-444.401 106.853,-444.401 94.8526,-432.401 94.8526,-397.599 106.853,-385.599 217.147,-385.599 229.147,-397.599 229.147,-432.401 217.147,-444.401"></polygon>
<path fill="white" stroke="white" d="M106.853,-444.401C100.853,-444.401 94.8526,-438.401 94.8526,-432.401"></path>
<path fill="white" stroke="white" d="M94.8526,-397.599C94.8526,-391.599 100.853,-385.599 106.853,-385.599"></path>
<path fill="white" stroke="white" d="M217.147,-385.599C223.147,-385.599 229.147,-391.599 229.147,-397.599"></path>
<path fill="white" stroke="white" d="M229.147,-432.401C229.147,-438.401 223.147,-444.401 217.147,-444.401"></path>
<polyline fill="none" stroke="black" points="217.147,-444.401 106.853,-444.401 "></polyline>
<path fill="none" stroke="black" d="M106.853,-444.401C100.853,-444.401 94.8526,-438.401 94.8526,-432.401"></path>
<polyline fill="none" stroke="black" points="94.8526,-432.401 94.8526,-397.599 "></polyline>
<path fill="none" stroke="black" d="M94.8526,-397.599C94.8526,-391.599 100.853,-385.599 106.853,-385.599"></path>
<polyline fill="none" stroke="black" points="106.853,-385.599 217.147,-385.599 "></polyline>
<path fill="none" stroke="black" d="M217.147,-385.599C223.147,-385.599 229.147,-391.599 229.147,-397.599"></path>
<polyline fill="none" stroke="black" points="229.147,-397.599 229.147,-432.401 "></polyline>
<path fill="none" stroke="black" d="M229.147,-432.401C229.147,-438.401 223.147,-444.401 217.147,-444.401"></path>
<text text-anchor="middle" x="162" y="-427.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="162" y="-410.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="162" y="-394" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M135.753,-480.524C139.43,-471.486 143.177,-462.273 146.646,-453.744"></path>
<polygon fill="black" stroke="black" points="149.9,-455.033 150.426,-444.452 143.416,-452.396 149.9,-455.033"></polygon>
</g>
<g id="node5" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="122.147,-349.601 11.8526,-349.601 -0.147372,-337.601 -0.147372,-236.399 11.8526,-224.399 122.147,-224.399 134.147,-236.399 134.147,-337.601 122.147,-349.601"></polygon>
<path fill="white" stroke="white" d="M11.8526,-349.601C5.85263,-349.601 -0.147372,-343.601 -0.147372,-337.601"></path>
<path fill="white" stroke="white" d="M-0.147372,-236.399C-0.147372,-230.399 5.85263,-224.399 11.8526,-224.399"></path>
<path fill="white" stroke="white" d="M122.147,-224.399C128.147,-224.399 134.147,-230.399 134.147,-236.399"></path>
<path fill="white" stroke="white" d="M134.147,-337.601C134.147,-343.601 128.147,-349.601 122.147,-349.601"></path>
<polyline fill="none" stroke="black" points="122.147,-349.601 11.8526,-349.601 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-349.601C5.85263,-349.601 -0.147372,-343.601 -0.147372,-337.601"></path>
<polyline fill="none" stroke="black" points="-0.147372,-337.601 -0.147372,-236.399 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-236.399C-0.147372,-230.399 5.85263,-224.399 11.8526,-224.399"></path>
<polyline fill="none" stroke="black" points="11.8526,-224.399 122.147,-224.399 "></polyline>
<path fill="none" stroke="black" d="M122.147,-224.399C128.147,-224.399 134.147,-230.399 134.147,-236.399"></path>
<polyline fill="none" stroke="black" points="134.147,-236.399 134.147,-337.601 "></polyline>
<path fill="none" stroke="black" d="M134.147,-337.601C134.147,-343.601 128.147,-349.601 122.147,-349.601"></path>
<text text-anchor="middle" x="67" y="-333.2" font-family="Times,serif" font-size="14.00">CatchClause</text>
<text text-anchor="middle" x="67" y="-316.4" font-family="Times,serif" font-size="14.00">Identifier (err)</text>
<text text-anchor="middle" x="67" y="-299.6" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-282.8" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-266" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-249.2" font-family="Times,serif" font-size="14.00">Identifier (hoge)</text>
<text text-anchor="middle" x="67" y="-232.4" font-family="Times,serif" font-size="14.00">Identifier (err)</text>
</g>
<g id="edge7" class="edge"><title>s1_1-&gt;s1_3</title>
<path fill="none" stroke="black" d="M95.6637,-480.644C92.0449,-468.693 88.5753,-456 86,-444 80.162,-416.798 75.9602,-386.514 73.0174,-359.921"></path>
<polygon fill="black" stroke="black" points="76.492,-359.495 71.9505,-349.923 69.5315,-360.238 76.492,-359.495"></polygon>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M140.68,-385.723C134.355,-377.334 127.129,-367.75 119.731,-357.939"></path>
<polygon fill="black" stroke="black" points="122.308,-355.543 113.493,-349.665 116.719,-359.757 122.308,-355.543"></polygon>
</g>
<g id="node6" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="169.147,-187.601 58.8526,-187.601 46.8526,-175.601 46.8526,-74.3994 58.8526,-62.3994 169.147,-62.3994 181.147,-74.3994 181.147,-175.601 169.147,-187.601"></polygon>
<path fill="white" stroke="white" d="M58.8526,-187.601C52.8526,-187.601 46.8526,-181.601 46.8526,-175.601"></path>
<path fill="white" stroke="white" d="M46.8526,-74.3994C46.8526,-68.3994 52.8526,-62.3994 58.8526,-62.3994"></path>
<path fill="white" stroke="white" d="M169.147,-62.3994C175.147,-62.3994 181.147,-68.3994 181.147,-74.3994"></path>
<path fill="white" stroke="white" d="M181.147,-175.601C181.147,-181.601 175.147,-187.601 169.147,-187.601"></path>
<polyline fill="none" stroke="black" points="169.147,-187.601 58.8526,-187.601 "></polyline>
<path fill="none" stroke="black" d="M58.8526,-187.601C52.8526,-187.601 46.8526,-181.601 46.8526,-175.601"></path>
<polyline fill="none" stroke="black" points="46.8526,-175.601 46.8526,-74.3994 "></polyline>
<path fill="none" stroke="black" d="M46.8526,-74.3994C46.8526,-68.3994 52.8526,-62.3994 58.8526,-62.3994"></path>
<polyline fill="none" stroke="black" points="58.8526,-62.3994 169.147,-62.3994 "></polyline>
<path fill="none" stroke="black" d="M169.147,-62.3994C175.147,-62.3994 181.147,-68.3994 181.147,-74.3994"></path>
<polyline fill="none" stroke="black" points="181.147,-74.3994 181.147,-175.601 "></polyline>
<path fill="none" stroke="black" d="M181.147,-175.601C181.147,-181.601 175.147,-187.601 169.147,-187.601"></path>
<text text-anchor="middle" x="114" y="-171.2" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="114" y="-154.4" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="114" y="-137.6" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="114" y="-120.8" font-family="Times,serif" font-size="14.00">Identifier (fuga)</text>
<text text-anchor="middle" x="114" y="-104" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="114" y="-87.2" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="114" y="-70.4" font-family="Times,serif" font-size="14.00">Identifier (last)</text>
</g>
<g id="edge9" class="edge"><title>s1_2-&gt;s1_4</title>
<path fill="none" stroke="black" d="M160.835,-385.75C158.918,-348.425 154.135,-280.766 143,-224 141.313,-215.398 139.196,-206.466 136.88,-197.651"></path>
<polygon fill="black" stroke="black" points="140.195,-196.504 134.191,-187.774 133.441,-198.342 140.195,-196.504"></polygon>
</g>
<g id="edge5" class="edge"><title>s1_3-&gt;s1_4</title>
<path fill="none" stroke="black" d="M85.1714,-224.14C87.7514,-215.357 90.4217,-206.266 93.0491,-197.322"></path>
<polygon fill="black" stroke="black" points="96.4165,-198.277 95.8769,-187.696 89.7003,-196.304 96.4165,-198.277"></polygon>
</g>
<g id="edge10" class="edge"><title>s1_4-&gt;final</title>
<path fill="none" stroke="black" d="M114,-62.2476C114,-53.0345 114,-44.0781 114,-36.4335"></path>
<polygon fill="black" stroke="black" points="117.5,-36.2949 114,-26.2949 110.5,-36.2949 117.5,-36.2949"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,186 @@
<?xml version="1.0"?>
<svg width="323pt" height="680pt" viewBox="0.00 0.00 323.00 680.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 676)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="248" cy="-663" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="303.147,-617.3 192.853,-617.3 180.853,-605.3 180.853,-520.7 192.853,-508.7 303.147,-508.7 315.147,-520.7 315.147,-605.3 303.147,-617.3"></polygon>
<path fill="white" stroke="white" d="M192.853,-617.3C186.853,-617.3 180.853,-611.3 180.853,-605.3"></path>
<path fill="white" stroke="white" d="M180.853,-520.7C180.853,-514.7 186.853,-508.7 192.853,-508.7"></path>
<path fill="white" stroke="white" d="M303.147,-508.7C309.147,-508.7 315.147,-514.7 315.147,-520.7"></path>
<path fill="white" stroke="white" d="M315.147,-605.3C315.147,-611.3 309.147,-617.3 303.147,-617.3"></path>
<polyline fill="none" stroke="black" points="303.147,-617.3 192.853,-617.3 "></polyline>
<path fill="none" stroke="black" d="M192.853,-617.3C186.853,-617.3 180.853,-611.3 180.853,-605.3"></path>
<polyline fill="none" stroke="black" points="180.853,-605.3 180.853,-520.7 "></polyline>
<path fill="none" stroke="black" d="M180.853,-520.7C180.853,-514.7 186.853,-508.7 192.853,-508.7"></path>
<polyline fill="none" stroke="black" points="192.853,-508.7 303.147,-508.7 "></polyline>
<path fill="none" stroke="black" d="M303.147,-508.7C309.147,-508.7 315.147,-514.7 315.147,-520.7"></path>
<polyline fill="none" stroke="black" points="315.147,-520.7 315.147,-605.3 "></polyline>
<path fill="none" stroke="black" d="M315.147,-605.3C315.147,-611.3 309.147,-617.3 303.147,-617.3"></path>
<text text-anchor="middle" x="248" y="-600.8" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="248" y="-584" font-family="Times,serif" font-size="14.00">TryStatement</text>
<text text-anchor="middle" x="248" y="-567.2" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="248" y="-550.4" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="248" y="-533.6" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="248" y="-516.8" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M248,-653.98C248,-647.675 248,-638.238 248,-627.813"></path>
<polygon fill="black" stroke="black" points="251.5,-627.586 248,-617.586 244.5,-627.586 251.5,-627.586"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="142" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="142" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="238.339,-471.602 175.661,-471.602 163.661,-459.602 163.661,-442.398 175.661,-430.398 238.339,-430.398 250.339,-442.398 250.339,-459.602 238.339,-471.602"></polygon>
<path fill="white" stroke="white" d="M175.661,-471.602C169.661,-471.602 163.661,-465.602 163.661,-459.602"></path>
<path fill="white" stroke="white" d="M163.661,-442.398C163.661,-436.398 169.661,-430.398 175.661,-430.398"></path>
<path fill="white" stroke="white" d="M238.339,-430.398C244.339,-430.398 250.339,-436.398 250.339,-442.398"></path>
<path fill="white" stroke="white" d="M250.339,-459.602C250.339,-465.602 244.339,-471.602 238.339,-471.602"></path>
<polyline fill="none" stroke="black" points="238.339,-471.602 175.661,-471.602 "></polyline>
<path fill="none" stroke="black" d="M175.661,-471.602C169.661,-471.602 163.661,-465.602 163.661,-459.602"></path>
<polyline fill="none" stroke="black" points="163.661,-459.602 163.661,-442.398 "></polyline>
<path fill="none" stroke="black" d="M163.661,-442.398C163.661,-436.398 169.661,-430.398 175.661,-430.398"></path>
<polyline fill="none" stroke="black" points="175.661,-430.398 238.339,-430.398 "></polyline>
<path fill="none" stroke="black" d="M238.339,-430.398C244.339,-430.398 250.339,-436.398 250.339,-442.398"></path>
<polyline fill="none" stroke="black" points="250.339,-442.398 250.339,-459.602 "></polyline>
<path fill="none" stroke="black" d="M250.339,-459.602C250.339,-465.602 244.339,-471.602 238.339,-471.602"></path>
<text text-anchor="middle" x="207" y="-455.2" font-family="Times,serif" font-size="14.00">IfStatement</text>
<text text-anchor="middle" x="207" y="-438.4" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M228.101,-508.611C224.581,-499.169 221.038,-489.663 217.887,-481.208"></path>
<polygon fill="black" stroke="black" points="221.164,-479.98 214.392,-471.833 214.605,-482.425 221.164,-479.98"></polygon>
</g>
<g id="node7" class="node"><title>s1_6</title>
<polygon fill="white" stroke="white" points="250.147,-281.601 139.853,-281.601 127.853,-269.601 127.853,-168.399 139.853,-156.399 250.147,-156.399 262.147,-168.399 262.147,-269.601 250.147,-281.601"></polygon>
<path fill="white" stroke="white" d="M139.853,-281.601C133.853,-281.601 127.853,-275.601 127.853,-269.601"></path>
<path fill="white" stroke="white" d="M127.853,-168.399C127.853,-162.399 133.853,-156.399 139.853,-156.399"></path>
<path fill="white" stroke="white" d="M250.147,-156.399C256.147,-156.399 262.147,-162.399 262.147,-168.399"></path>
<path fill="white" stroke="white" d="M262.147,-269.601C262.147,-275.601 256.147,-281.601 250.147,-281.601"></path>
<polyline fill="none" stroke="black" points="250.147,-281.601 139.853,-281.601 "></polyline>
<path fill="none" stroke="black" d="M139.853,-281.601C133.853,-281.601 127.853,-275.601 127.853,-269.601"></path>
<polyline fill="none" stroke="black" points="127.853,-269.601 127.853,-168.399 "></polyline>
<path fill="none" stroke="black" d="M127.853,-168.399C127.853,-162.399 133.853,-156.399 139.853,-156.399"></path>
<polyline fill="none" stroke="black" points="139.853,-156.399 250.147,-156.399 "></polyline>
<path fill="none" stroke="black" d="M250.147,-156.399C256.147,-156.399 262.147,-162.399 262.147,-168.399"></path>
<polyline fill="none" stroke="black" points="262.147,-168.399 262.147,-269.601 "></polyline>
<path fill="none" stroke="black" d="M262.147,-269.601C262.147,-275.601 256.147,-281.601 250.147,-281.601"></path>
<text text-anchor="middle" x="195" y="-265.2" font-family="Times,serif" font-size="14.00">CatchClause</text>
<text text-anchor="middle" x="195" y="-248.4" font-family="Times,serif" font-size="14.00">Identifier (err)</text>
<text text-anchor="middle" x="195" y="-231.6" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="195" y="-214.8" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="195" y="-198" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="195" y="-181.2" font-family="Times,serif" font-size="14.00">Identifier (hoge)</text>
<text text-anchor="middle" x="195" y="-164.4" font-family="Times,serif" font-size="14.00">Identifier (err)</text>
</g>
<g id="edge9" class="edge"><title>s1_1-&gt;s1_6</title>
<path fill="none" stroke="black" d="M265.496,-508.624C279.169,-458.161 292.566,-381 271,-318 267.758,-308.528 263.185,-299.263 257.874,-290.444"></path>
<polygon fill="black" stroke="black" points="260.672,-288.323 252.338,-281.781 254.774,-292.092 260.672,-288.323"></polygon>
</g>
<g id="node5" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="250.329,-393.7 163.671,-393.7 151.671,-381.7 151.671,-330.3 163.671,-318.3 250.329,-318.3 262.329,-330.3 262.329,-381.7 250.329,-393.7"></polygon>
<path fill="white" stroke="white" d="M163.671,-393.7C157.671,-393.7 151.671,-387.7 151.671,-381.7"></path>
<path fill="white" stroke="white" d="M151.671,-330.3C151.671,-324.3 157.671,-318.3 163.671,-318.3"></path>
<path fill="white" stroke="white" d="M250.329,-318.3C256.329,-318.3 262.329,-324.3 262.329,-330.3"></path>
<path fill="white" stroke="white" d="M262.329,-381.7C262.329,-387.7 256.329,-393.7 250.329,-393.7"></path>
<polyline fill="none" stroke="black" points="250.329,-393.7 163.671,-393.7 "></polyline>
<path fill="none" stroke="black" d="M163.671,-393.7C157.671,-393.7 151.671,-387.7 151.671,-381.7"></path>
<polyline fill="none" stroke="black" points="151.671,-381.7 151.671,-330.3 "></polyline>
<path fill="none" stroke="black" d="M151.671,-330.3C151.671,-324.3 157.671,-318.3 163.671,-318.3"></path>
<polyline fill="none" stroke="black" points="163.671,-318.3 250.329,-318.3 "></polyline>
<path fill="none" stroke="black" d="M250.329,-318.3C256.329,-318.3 262.329,-324.3 262.329,-330.3"></path>
<polyline fill="none" stroke="black" points="262.329,-330.3 262.329,-381.7 "></polyline>
<path fill="none" stroke="black" d="M262.329,-381.7C262.329,-387.7 256.329,-393.7 250.329,-393.7"></path>
<text text-anchor="middle" x="207" y="-377" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="207" y="-360.2" font-family="Times,serif" font-size="14.00">ThrowStatement</text>
<text text-anchor="middle" x="207" y="-343.4" font-family="Times,serif" font-size="14.00">NewExpression</text>
<text text-anchor="middle" x="207" y="-326.6" font-family="Times,serif" font-size="14.00">Identifier (Error)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M207,-430.277C207,-422.524 207,-413.265 207,-403.98"></path>
<polygon fill="black" stroke="black" points="210.5,-403.965 207,-393.965 203.5,-403.965 210.5,-403.965"></polygon>
</g>
<g id="node6" class="node"><title>s1_5</title>
<polygon fill="white" stroke="white" points="122.147,-385.401 11.8526,-385.401 -0.147372,-373.401 -0.147372,-338.599 11.8526,-326.599 122.147,-326.599 134.147,-338.599 134.147,-373.401 122.147,-385.401"></polygon>
<path fill="white" stroke="white" d="M11.8526,-385.401C5.85263,-385.401 -0.147372,-379.401 -0.147372,-373.401"></path>
<path fill="white" stroke="white" d="M-0.147372,-338.599C-0.147372,-332.599 5.85263,-326.599 11.8526,-326.599"></path>
<path fill="white" stroke="white" d="M122.147,-326.599C128.147,-326.599 134.147,-332.599 134.147,-338.599"></path>
<path fill="white" stroke="white" d="M134.147,-373.401C134.147,-379.401 128.147,-385.401 122.147,-385.401"></path>
<polyline fill="none" stroke="black" points="122.147,-385.401 11.8526,-385.401 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-385.401C5.85263,-385.401 -0.147372,-379.401 -0.147372,-373.401"></path>
<polyline fill="none" stroke="black" points="-0.147372,-373.401 -0.147372,-338.599 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-338.599C-0.147372,-332.599 5.85263,-326.599 11.8526,-326.599"></path>
<polyline fill="none" stroke="black" points="11.8526,-326.599 122.147,-326.599 "></polyline>
<path fill="none" stroke="black" d="M122.147,-326.599C128.147,-326.599 134.147,-332.599 134.147,-338.599"></path>
<polyline fill="none" stroke="black" points="134.147,-338.599 134.147,-373.401 "></polyline>
<path fill="none" stroke="black" d="M134.147,-373.401C134.147,-379.401 128.147,-385.401 122.147,-385.401"></path>
<text text-anchor="middle" x="67" y="-368.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-351.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-335" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge11" class="edge"><title>s1_2-&gt;s1_5</title>
<path fill="none" stroke="black" d="M177.31,-430.277C160.103,-418.847 137.967,-404.142 118.045,-390.909"></path>
<polygon fill="black" stroke="black" points="119.93,-387.959 109.664,-385.341 116.057,-393.79 119.93,-387.959"></polygon>
</g>
<g id="edge13" class="edge"><title>s1_3-&gt;s1_6</title>
<path fill="none" stroke="black" d="M203.721,-318.111C202.995,-309.943 202.201,-301.016 201.398,-291.982"></path>
<polygon fill="black" stroke="black" points="204.863,-291.422 200.491,-281.771 197.89,-292.042 204.863,-291.422"></polygon>
</g>
<g id="edge6" class="edge"><title>s1_5-&gt;s1_6</title>
<path fill="none" stroke="black" d="M93.833,-326.7C104.348,-315.609 116.912,-302.359 129.551,-289.029"></path>
<polygon fill="black" stroke="black" points="132.227,-291.293 136.567,-281.628 127.147,-286.477 132.227,-291.293"></polygon>
</g>
<g id="node8" class="node"><title>s1_7</title>
<polygon fill="white" stroke="white" points="197.147,-120.401 86.8526,-120.401 74.8526,-108.401 74.8526,-73.5986 86.8526,-61.5986 197.147,-61.5986 209.147,-73.5986 209.147,-108.401 197.147,-120.401"></polygon>
<path fill="white" stroke="white" d="M86.8526,-120.401C80.8526,-120.401 74.8526,-114.401 74.8526,-108.401"></path>
<path fill="white" stroke="white" d="M74.8526,-73.5986C74.8526,-67.5986 80.8526,-61.5986 86.8526,-61.5986"></path>
<path fill="white" stroke="white" d="M197.147,-61.5986C203.147,-61.5986 209.147,-67.5986 209.147,-73.5986"></path>
<path fill="white" stroke="white" d="M209.147,-108.401C209.147,-114.401 203.147,-120.401 197.147,-120.401"></path>
<polyline fill="none" stroke="black" points="197.147,-120.401 86.8526,-120.401 "></polyline>
<path fill="none" stroke="black" d="M86.8526,-120.401C80.8526,-120.401 74.8526,-114.401 74.8526,-108.401"></path>
<polyline fill="none" stroke="black" points="74.8526,-108.401 74.8526,-73.5986 "></polyline>
<path fill="none" stroke="black" d="M74.8526,-73.5986C74.8526,-67.5986 80.8526,-61.5986 86.8526,-61.5986"></path>
<polyline fill="none" stroke="black" points="86.8526,-61.5986 197.147,-61.5986 "></polyline>
<path fill="none" stroke="black" d="M197.147,-61.5986C203.147,-61.5986 209.147,-67.5986 209.147,-73.5986"></path>
<polyline fill="none" stroke="black" points="209.147,-73.5986 209.147,-108.401 "></polyline>
<path fill="none" stroke="black" d="M209.147,-108.401C209.147,-114.401 203.147,-120.401 197.147,-120.401"></path>
<text text-anchor="middle" x="142" y="-103.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="142" y="-86.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="142" y="-70" font-family="Times,serif" font-size="14.00">Identifier (last)</text>
</g>
<g id="edge15" class="edge"><title>s1_5-&gt;s1_7</title>
<path fill="none" stroke="black" d="M73.536,-326.764C82.7028,-287.987 100.357,-216.205 119,-156 121.611,-147.569 124.658,-138.605 127.664,-130.139"></path>
<polygon fill="black" stroke="black" points="131.044,-131.083 131.145,-120.489 124.459,-128.708 131.044,-131.083"></polygon>
</g>
<g id="edge7" class="edge"><title>s1_6-&gt;s1_7</title>
<path fill="none" stroke="black" d="M168.966,-156.107C165.165,-147.072 161.351,-138.005 157.838,-129.652"></path>
<polygon fill="black" stroke="black" points="160.974,-128.08 153.87,-120.219 154.521,-130.794 160.974,-128.08"></polygon>
</g>
<g id="edge16" class="edge"><title>s1_7-&gt;final</title>
<path fill="none" stroke="black" d="M142,-61.7004C142,-53.2282 142,-44.0665 142,-36.0585"></path>
<polygon fill="black" stroke="black" points="145.5,-36.0267 142,-26.0267 138.5,-36.0267 145.5,-36.0267"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,139 @@
<?xml version="1.0"?>
<svg width="294pt" height="490pt" viewBox="0.00 0.00 294.00 490.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 486)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="171" cy="-473" rx="9" ry="9"></ellipse>
</g>
<g id="node4" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="226.147,-427.3 115.853,-427.3 103.853,-415.3 103.853,-330.7 115.853,-318.7 226.147,-318.7 238.147,-330.7 238.147,-415.3 226.147,-427.3"></polygon>
<path fill="white" stroke="white" d="M115.853,-427.3C109.853,-427.3 103.853,-421.3 103.853,-415.3"></path>
<path fill="white" stroke="white" d="M103.853,-330.7C103.853,-324.7 109.853,-318.7 115.853,-318.7"></path>
<path fill="white" stroke="white" d="M226.147,-318.7C232.147,-318.7 238.147,-324.7 238.147,-330.7"></path>
<path fill="white" stroke="white" d="M238.147,-415.3C238.147,-421.3 232.147,-427.3 226.147,-427.3"></path>
<polyline fill="none" stroke="black" points="226.147,-427.3 115.853,-427.3 "></polyline>
<path fill="none" stroke="black" d="M115.853,-427.3C109.853,-427.3 103.853,-421.3 103.853,-415.3"></path>
<polyline fill="none" stroke="black" points="103.853,-415.3 103.853,-330.7 "></polyline>
<path fill="none" stroke="black" d="M103.853,-330.7C103.853,-324.7 109.853,-318.7 115.853,-318.7"></path>
<polyline fill="none" stroke="black" points="115.853,-318.7 226.147,-318.7 "></polyline>
<path fill="none" stroke="black" d="M226.147,-318.7C232.147,-318.7 238.147,-324.7 238.147,-330.7"></path>
<polyline fill="none" stroke="black" points="238.147,-330.7 238.147,-415.3 "></polyline>
<path fill="none" stroke="black" d="M238.147,-415.3C238.147,-421.3 232.147,-427.3 226.147,-427.3"></path>
<text text-anchor="middle" x="171" y="-410.8" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="171" y="-394" font-family="Times,serif" font-size="14.00">TryStatement</text>
<text text-anchor="middle" x="171" y="-377.2" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="171" y="-360.4" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="171" y="-343.6" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="171" y="-326.8" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M171,-463.98C171,-457.675 171,-448.238 171,-437.813"></path>
<polygon fill="black" stroke="black" points="174.5,-437.586 171,-427.586 167.5,-437.586 174.5,-437.586"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="67" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="67" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node3" class="node"><title>thrown</title>
<ellipse fill="white" stroke="black" cx="219" cy="-13" rx="11" ry="11"></ellipse>
<text text-anchor="middle" x="219" y="-8.8" font-family="Times,serif" font-size="14.00"></text>
</g>
<g id="node5" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="179.147,-282.401 68.8526,-282.401 56.8526,-270.401 56.8526,-235.599 68.8526,-223.599 179.147,-223.599 191.147,-235.599 191.147,-270.401 179.147,-282.401"></polygon>
<path fill="white" stroke="white" d="M68.8526,-282.401C62.8526,-282.401 56.8526,-276.401 56.8526,-270.401"></path>
<path fill="white" stroke="white" d="M56.8526,-235.599C56.8526,-229.599 62.8526,-223.599 68.8526,-223.599"></path>
<path fill="white" stroke="white" d="M179.147,-223.599C185.147,-223.599 191.147,-229.599 191.147,-235.599"></path>
<path fill="white" stroke="white" d="M191.147,-270.401C191.147,-276.401 185.147,-282.401 179.147,-282.401"></path>
<polyline fill="none" stroke="black" points="179.147,-282.401 68.8526,-282.401 "></polyline>
<path fill="none" stroke="black" d="M68.8526,-282.401C62.8526,-282.401 56.8526,-276.401 56.8526,-270.401"></path>
<polyline fill="none" stroke="black" points="56.8526,-270.401 56.8526,-235.599 "></polyline>
<path fill="none" stroke="black" d="M56.8526,-235.599C56.8526,-229.599 62.8526,-223.599 68.8526,-223.599"></path>
<polyline fill="none" stroke="black" points="68.8526,-223.599 179.147,-223.599 "></polyline>
<path fill="none" stroke="black" d="M179.147,-223.599C185.147,-223.599 191.147,-229.599 191.147,-235.599"></path>
<polyline fill="none" stroke="black" points="191.147,-235.599 191.147,-270.401 "></polyline>
<path fill="none" stroke="black" d="M191.147,-270.401C191.147,-276.401 185.147,-282.401 179.147,-282.401"></path>
<text text-anchor="middle" x="124" y="-265.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="124" y="-248.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="124" y="-232" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M149.7,-318.524C146.1,-309.486 142.431,-300.273 139.034,-291.744"></path>
<polygon fill="black" stroke="black" points="142.284,-290.447 135.332,-282.452 135.781,-293.037 142.284,-290.447"></polygon>
</g>
<g id="node7" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="274.147,-162.7 163.853,-162.7 151.853,-150.7 151.853,-99.2997 163.853,-87.2997 274.147,-87.2997 286.147,-99.2997 286.147,-150.7 274.147,-162.7"></polygon>
<path fill="white" stroke="white" d="M163.853,-162.7C157.853,-162.7 151.853,-156.7 151.853,-150.7"></path>
<path fill="white" stroke="white" d="M151.853,-99.2997C151.853,-93.2997 157.853,-87.2997 163.853,-87.2997"></path>
<path fill="white" stroke="white" d="M274.147,-87.2997C280.147,-87.2997 286.147,-93.2997 286.147,-99.2997"></path>
<path fill="white" stroke="white" d="M286.147,-150.7C286.147,-156.7 280.147,-162.7 274.147,-162.7"></path>
<polyline fill="none" stroke="black" points="274.147,-162.7 163.853,-162.7 "></polyline>
<path fill="none" stroke="black" d="M163.853,-162.7C157.853,-162.7 151.853,-156.7 151.853,-150.7"></path>
<polyline fill="none" stroke="black" points="151.853,-150.7 151.853,-99.2997 "></polyline>
<path fill="none" stroke="black" d="M151.853,-99.2997C151.853,-93.2997 157.853,-87.2997 163.853,-87.2997"></path>
<polyline fill="none" stroke="black" points="163.853,-87.2997 274.147,-87.2997 "></polyline>
<path fill="none" stroke="black" d="M274.147,-87.2997C280.147,-87.2997 286.147,-93.2997 286.147,-99.2997"></path>
<polyline fill="none" stroke="black" points="286.147,-99.2997 286.147,-150.7 "></polyline>
<path fill="none" stroke="black" d="M286.147,-150.7C286.147,-156.7 280.147,-162.7 274.147,-162.7"></path>
<text text-anchor="middle" x="219" y="-146" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="219" y="-129.2" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="219" y="-112.4" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="219" y="-95.6" font-family="Times,serif" font-size="14.00">Identifier (fuga)</text>
</g>
<g id="edge6" class="edge"><title>s1_1-&gt;s1_4</title>
<path fill="none" stroke="black" d="M190.026,-318.681C193.772,-306.729 197.356,-294.025 200,-282 207.95,-245.85 212.809,-204.204 215.622,-173.04"></path>
<polygon fill="black" stroke="black" points="219.124,-173.16 216.499,-162.896 212.15,-172.557 219.124,-173.16"></polygon>
</g>
<g id="node6" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="122.147,-187.601 11.8526,-187.601 -0.147372,-175.601 -0.147372,-74.3994 11.8526,-62.3994 122.147,-62.3994 134.147,-74.3994 134.147,-175.601 122.147,-187.601"></polygon>
<path fill="white" stroke="white" d="M11.8526,-187.601C5.85263,-187.601 -0.147372,-181.601 -0.147372,-175.601"></path>
<path fill="white" stroke="white" d="M-0.147372,-74.3994C-0.147372,-68.3994 5.85263,-62.3994 11.8526,-62.3994"></path>
<path fill="white" stroke="white" d="M122.147,-62.3994C128.147,-62.3994 134.147,-68.3994 134.147,-74.3994"></path>
<path fill="white" stroke="white" d="M134.147,-175.601C134.147,-181.601 128.147,-187.601 122.147,-187.601"></path>
<polyline fill="none" stroke="black" points="122.147,-187.601 11.8526,-187.601 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-187.601C5.85263,-187.601 -0.147372,-181.601 -0.147372,-175.601"></path>
<polyline fill="none" stroke="black" points="-0.147372,-175.601 -0.147372,-74.3994 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-74.3994C-0.147372,-68.3994 5.85263,-62.3994 11.8526,-62.3994"></path>
<polyline fill="none" stroke="black" points="11.8526,-62.3994 122.147,-62.3994 "></polyline>
<path fill="none" stroke="black" d="M122.147,-62.3994C128.147,-62.3994 134.147,-68.3994 134.147,-74.3994"></path>
<polyline fill="none" stroke="black" points="134.147,-74.3994 134.147,-175.601 "></polyline>
<path fill="none" stroke="black" d="M134.147,-175.601C134.147,-181.601 128.147,-187.601 122.147,-187.601"></path>
<text text-anchor="middle" x="67" y="-171.2" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-154.4" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-137.6" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-120.8" font-family="Times,serif" font-size="14.00">Identifier (fuga)</text>
<text text-anchor="middle" x="67" y="-104" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-87.2" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-70.4" font-family="Times,serif" font-size="14.00">Identifier (last)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M111.208,-223.723C107.527,-215.585 103.337,-206.324 99.038,-196.821"></path>
<polygon fill="black" stroke="black" points="102.207,-195.333 94.896,-187.665 95.8289,-198.219 102.207,-195.333"></polygon>
</g>
<g id="edge8" class="edge"><title>s1_2-&gt;s1_4</title>
<path fill="none" stroke="black" d="M145.32,-223.723C156.979,-208.26 171.698,-188.737 184.91,-171.214"></path>
<polygon fill="black" stroke="black" points="188.029,-172.891 191.255,-162.799 182.44,-168.677 188.029,-172.891"></polygon>
</g>
<g id="edge10" class="edge"><title>s1_3-&gt;final</title>
<path fill="none" stroke="black" d="M67,-62.2476C67,-53.0345 67,-44.0781 67,-36.4335"></path>
<polygon fill="black" stroke="black" points="70.5001,-36.2949 67,-26.2949 63.5001,-36.2949 70.5001,-36.2949"></polygon>
</g>
<g id="edge12" class="edge"><title>s1_4-&gt;thrown</title>
<path fill="none" stroke="black" d="M219,-87.3716C219,-69.6416 219,-49.034 219,-34.1808"></path>
<polygon fill="black" stroke="black" points="222.5,-34.087 219,-24.087 215.5,-34.087 222.5,-34.087"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,99 @@
<?xml version="1.0"?>
<svg width="270pt" height="328pt" viewBox="0.00 0.00 270.00 328.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 324)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="125" cy="-311" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s2_1</title>
<polygon fill="white" stroke="white" points="178.307,-265.3 71.6933,-265.3 59.6933,-253.3 59.6933,-168.7 71.6933,-156.7 178.307,-156.7 190.307,-168.7 190.307,-253.3 178.307,-265.3"></polygon>
<path fill="white" stroke="white" d="M71.6933,-265.3C65.6933,-265.3 59.6933,-259.3 59.6933,-253.3"></path>
<path fill="white" stroke="white" d="M59.6933,-168.7C59.6933,-162.7 65.6933,-156.7 71.6933,-156.7"></path>
<path fill="white" stroke="white" d="M178.307,-156.7C184.307,-156.7 190.307,-162.7 190.307,-168.7"></path>
<path fill="white" stroke="white" d="M190.307,-253.3C190.307,-259.3 184.307,-265.3 178.307,-265.3"></path>
<polyline fill="none" stroke="black" points="178.307,-265.3 71.6933,-265.3 "></polyline>
<path fill="none" stroke="black" d="M71.6933,-265.3C65.6933,-265.3 59.6933,-259.3 59.6933,-253.3"></path>
<polyline fill="none" stroke="black" points="59.6933,-253.3 59.6933,-168.7 "></polyline>
<path fill="none" stroke="black" d="M59.6933,-168.7C59.6933,-162.7 65.6933,-156.7 71.6933,-156.7"></path>
<polyline fill="none" stroke="black" points="71.6933,-156.7 178.307,-156.7 "></polyline>
<path fill="none" stroke="black" d="M178.307,-156.7C184.307,-156.7 190.307,-162.7 190.307,-168.7"></path>
<polyline fill="none" stroke="black" points="190.307,-168.7 190.307,-253.3 "></polyline>
<path fill="none" stroke="black" d="M190.307,-253.3C190.307,-259.3 184.307,-265.3 178.307,-265.3"></path>
<text text-anchor="middle" x="125" y="-248.8" font-family="Times,serif" font-size="14.00">FunctionDeclaration</text>
<text text-anchor="middle" x="125" y="-232" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="125" y="-215.2" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
<text text-anchor="middle" x="125" y="-198.4" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="125" y="-181.6" font-family="Times,serif" font-size="14.00">IfStatement</text>
<text text-anchor="middle" x="125" y="-164.8" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s2_1</title>
<path fill="none" stroke="black" d="M125,-301.98C125,-295.675 125,-286.238 125,-275.813"></path>
<polygon fill="black" stroke="black" points="128.5,-275.586 125,-265.586 121.5,-275.586 128.5,-275.586"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="125" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="125" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s2_2</title>
<polygon fill="white" stroke="white" points="98.0684,-111.602 11.9316,-111.602 -0.0684189,-99.6019 -0.0684189,-82.3981 11.9316,-70.3981 98.0684,-70.3981 110.068,-82.3981 110.068,-99.6019 98.0684,-111.602"></polygon>
<path fill="white" stroke="white" d="M11.9316,-111.602C5.93158,-111.602 -0.0684189,-105.602 -0.0684189,-99.6019"></path>
<path fill="white" stroke="white" d="M-0.0684189,-82.3981C-0.0684189,-76.3981 5.93158,-70.3981 11.9316,-70.3981"></path>
<path fill="white" stroke="white" d="M98.0684,-70.3981C104.068,-70.3981 110.068,-76.3981 110.068,-82.3981"></path>
<path fill="white" stroke="white" d="M110.068,-99.6019C110.068,-105.602 104.068,-111.602 98.0684,-111.602"></path>
<polyline fill="none" stroke="black" points="98.0684,-111.602 11.9316,-111.602 "></polyline>
<path fill="none" stroke="black" d="M11.9316,-111.602C5.93158,-111.602 -0.0684189,-105.602 -0.0684189,-99.6019"></path>
<polyline fill="none" stroke="black" points="-0.0684189,-99.6019 -0.0684189,-82.3981 "></polyline>
<path fill="none" stroke="black" d="M-0.0684189,-82.3981C-0.0684189,-76.3981 5.93158,-70.3981 11.9316,-70.3981"></path>
<polyline fill="none" stroke="black" points="11.9316,-70.3981 98.0684,-70.3981 "></polyline>
<path fill="none" stroke="black" d="M98.0684,-70.3981C104.068,-70.3981 110.068,-76.3981 110.068,-82.3981"></path>
<polyline fill="none" stroke="black" points="110.068,-82.3981 110.068,-99.6019 "></polyline>
<path fill="none" stroke="black" d="M110.068,-99.6019C110.068,-105.602 104.068,-111.602 98.0684,-111.602"></path>
<text text-anchor="middle" x="55" y="-95.2" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="55" y="-78.4" font-family="Times,serif" font-size="14.00">ReturnStatement</text>
</g>
<g id="edge3" class="edge"><title>s2_1-&gt;s2_2</title>
<path fill="none" stroke="black" d="M93.277,-156.524C85.8726,-144.042 78.2709,-131.228 71.813,-120.342"></path>
<polygon fill="black" stroke="black" points="74.7991,-118.516 66.6869,-111.701 68.7787,-122.087 74.7991,-118.516"></polygon>
</g>
<g id="node5" class="node"><title>s2_4</title>
<polygon fill="white" stroke="white" points="250.147,-120.401 139.853,-120.401 127.853,-108.401 127.853,-73.5986 139.853,-61.5986 250.147,-61.5986 262.147,-73.5986 262.147,-108.401 250.147,-120.401"></polygon>
<path fill="white" stroke="white" d="M139.853,-120.401C133.853,-120.401 127.853,-114.401 127.853,-108.401"></path>
<path fill="white" stroke="white" d="M127.853,-73.5986C127.853,-67.5986 133.853,-61.5986 139.853,-61.5986"></path>
<path fill="white" stroke="white" d="M250.147,-61.5986C256.147,-61.5986 262.147,-67.5986 262.147,-73.5986"></path>
<path fill="white" stroke="white" d="M262.147,-108.401C262.147,-114.401 256.147,-120.401 250.147,-120.401"></path>
<polyline fill="none" stroke="black" points="250.147,-120.401 139.853,-120.401 "></polyline>
<path fill="none" stroke="black" d="M139.853,-120.401C133.853,-120.401 127.853,-114.401 127.853,-108.401"></path>
<polyline fill="none" stroke="black" points="127.853,-108.401 127.853,-73.5986 "></polyline>
<path fill="none" stroke="black" d="M127.853,-73.5986C127.853,-67.5986 133.853,-61.5986 139.853,-61.5986"></path>
<polyline fill="none" stroke="black" points="139.853,-61.5986 250.147,-61.5986 "></polyline>
<path fill="none" stroke="black" d="M250.147,-61.5986C256.147,-61.5986 262.147,-67.5986 262.147,-73.5986"></path>
<polyline fill="none" stroke="black" points="262.147,-73.5986 262.147,-108.401 "></polyline>
<path fill="none" stroke="black" d="M262.147,-108.401C262.147,-114.401 256.147,-120.401 250.147,-120.401"></path>
<text text-anchor="middle" x="195" y="-103.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="195" y="-86.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="195" y="-70" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge5" class="edge"><title>s2_1-&gt;s2_4</title>
<path fill="none" stroke="black" d="M156.723,-156.524C162.2,-147.291 167.785,-137.877 172.935,-129.195"></path>
<polygon fill="black" stroke="black" points="176.03,-130.838 178.122,-120.452 170.01,-127.267 176.03,-130.838"></polygon>
</g>
<g id="edge7" class="edge"><title>s2_2-&gt;final</title>
<path fill="none" stroke="black" d="M73.3917,-70.0319C84.6046,-57.8578 98.7782,-42.4693 109.434,-30.9007"></path>
<polygon fill="black" stroke="black" points="112.278,-32.9792 116.478,-23.2526 107.129,-28.2369 112.278,-32.9792"></polygon>
</g>
<g id="edge9" class="edge"><title>s2_4-&gt;final</title>
<path fill="none" stroke="black" d="M168.935,-61.7004C159.292,-51.2315 148.68,-39.7098 140.301,-30.6129"></path>
<polygon fill="black" stroke="black" points="142.676,-28.0244 133.326,-23.0401 137.527,-32.7668 142.676,-28.0244"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -0,0 +1,47 @@
<?xml version="1.0"?>
<svg width="142pt" height="234pt" viewBox="0.00 0.00 142.00 234.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 230)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="67" cy="-217" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="122.147,-171.3 11.8526,-171.3 -0.147372,-159.3 -0.147372,-74.6998 11.8526,-62.6998 122.147,-62.6998 134.147,-74.6998 134.147,-159.3 122.147,-171.3"></polygon>
<path fill="white" stroke="white" d="M11.8526,-171.3C5.85263,-171.3 -0.147372,-165.3 -0.147372,-159.3"></path>
<path fill="white" stroke="white" d="M-0.147372,-74.6998C-0.147372,-68.6998 5.85263,-62.6998 11.8526,-62.6998"></path>
<path fill="white" stroke="white" d="M122.147,-62.6998C128.147,-62.6998 134.147,-68.6998 134.147,-74.6998"></path>
<path fill="white" stroke="white" d="M134.147,-159.3C134.147,-165.3 128.147,-171.3 122.147,-171.3"></path>
<polyline fill="none" stroke="black" points="122.147,-171.3 11.8526,-171.3 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-171.3C5.85263,-171.3 -0.147372,-165.3 -0.147372,-159.3"></path>
<polyline fill="none" stroke="black" points="-0.147372,-159.3 -0.147372,-74.6998 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-74.6998C-0.147372,-68.6998 5.85263,-62.6998 11.8526,-62.6998"></path>
<polyline fill="none" stroke="black" points="11.8526,-62.6998 122.147,-62.6998 "></polyline>
<path fill="none" stroke="black" d="M122.147,-62.6998C128.147,-62.6998 134.147,-68.6998 134.147,-74.6998"></path>
<polyline fill="none" stroke="black" points="134.147,-74.6998 134.147,-159.3 "></polyline>
<path fill="none" stroke="black" d="M134.147,-159.3C134.147,-165.3 128.147,-171.3 122.147,-171.3"></path>
<text text-anchor="middle" x="67" y="-154.8" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="67" y="-138" font-family="Times,serif" font-size="14.00">FunctionDeclaration</text>
<text text-anchor="middle" x="67" y="-121.2" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-104.4" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-87.6" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="67" y="-70.8" font-family="Times,serif" font-size="14.00">Literal (false)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M67,-207.98C67,-201.675 67,-192.238 67,-181.813"></path>
<polygon fill="black" stroke="black" points="70.5001,-181.586 67,-171.586 63.5001,-181.586 70.5001,-181.586"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="67" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="67" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;final</title>
<path fill="none" stroke="black" d="M67,-62.6102C67,-53.3058 67,-44.1078 67,-36.2584"></path>
<polygon fill="black" stroke="black" points="70.5001,-36.1896 67,-26.1896 63.5001,-36.1897 70.5001,-36.1896"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,172 @@
<?xml version="1.0"?>
<svg width="408pt" height="416pt" viewBox="0.00 0.00 408.00 416.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 412)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="193" cy="-399" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="234.149,-353.602 151.851,-353.602 139.851,-341.602 139.851,-324.398 151.851,-312.398 234.149,-312.398 246.149,-324.398 246.149,-341.602 234.149,-353.602"></polygon>
<path fill="white" stroke="white" d="M151.851,-353.602C145.851,-353.602 139.851,-347.602 139.851,-341.602"></path>
<path fill="white" stroke="white" d="M139.851,-324.398C139.851,-318.398 145.851,-312.398 151.851,-312.398"></path>
<path fill="white" stroke="white" d="M234.149,-312.398C240.149,-312.398 246.149,-318.398 246.149,-324.398"></path>
<path fill="white" stroke="white" d="M246.149,-341.602C246.149,-347.602 240.149,-353.602 234.149,-353.602"></path>
<polyline fill="none" stroke="black" points="234.149,-353.602 151.851,-353.602 "></polyline>
<path fill="none" stroke="black" d="M151.851,-353.602C145.851,-353.602 139.851,-347.602 139.851,-341.602"></path>
<polyline fill="none" stroke="black" points="139.851,-341.602 139.851,-324.398 "></polyline>
<path fill="none" stroke="black" d="M139.851,-324.398C139.851,-318.398 145.851,-312.398 151.851,-312.398"></path>
<polyline fill="none" stroke="black" points="151.851,-312.398 234.149,-312.398 "></polyline>
<path fill="none" stroke="black" d="M234.149,-312.398C240.149,-312.398 246.149,-318.398 246.149,-324.398"></path>
<polyline fill="none" stroke="black" points="246.149,-324.398 246.149,-341.602 "></polyline>
<path fill="none" stroke="black" d="M246.149,-341.602C246.149,-347.602 240.149,-353.602 234.149,-353.602"></path>
<text text-anchor="middle" x="193" y="-337.2" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="193" y="-320.4" font-family="Times,serif" font-size="14.00">WhileStatement</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M193,-389.894C193,-383.274 193,-373.485 193,-363.94"></path>
<polygon fill="black" stroke="black" points="196.5,-363.842 193,-353.842 189.5,-363.842 196.5,-363.842"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="335" cy="-29" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="335" cy="-29" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="224.339,-276 161.661,-276 149.661,-264 149.661,-252 161.661,-240 224.339,-240 236.339,-252 236.339,-264 224.339,-276"></polygon>
<path fill="white" stroke="white" d="M161.661,-276C155.661,-276 149.661,-270 149.661,-264"></path>
<path fill="white" stroke="white" d="M149.661,-252C149.661,-246 155.661,-240 161.661,-240"></path>
<path fill="white" stroke="white" d="M224.339,-240C230.339,-240 236.339,-246 236.339,-252"></path>
<path fill="white" stroke="white" d="M236.339,-264C236.339,-270 230.339,-276 224.339,-276"></path>
<polyline fill="none" stroke="black" points="224.339,-276 161.661,-276 "></polyline>
<path fill="none" stroke="black" d="M161.661,-276C155.661,-276 149.661,-270 149.661,-264"></path>
<polyline fill="none" stroke="black" points="149.661,-264 149.661,-252 "></polyline>
<path fill="none" stroke="black" d="M149.661,-252C149.661,-246 155.661,-240 161.661,-240"></path>
<polyline fill="none" stroke="black" points="161.661,-240 224.339,-240 "></polyline>
<path fill="none" stroke="black" d="M224.339,-240C230.339,-240 236.339,-246 236.339,-252"></path>
<polyline fill="none" stroke="black" points="236.339,-252 236.339,-264 "></polyline>
<path fill="none" stroke="black" d="M236.339,-264C236.339,-270 230.339,-276 224.339,-276"></path>
<text text-anchor="middle" x="193" y="-253.8" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M193,-312.052C193,-304.216 193,-295.089 193,-286.636"></path>
<polygon fill="black" stroke="black" points="196.5,-286.439 193,-276.439 189.5,-286.439 196.5,-286.439"></polygon>
</g>
<g id="node5" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="201.147,-203.3 90.8526,-203.3 78.8526,-191.3 78.8526,-106.7 90.8526,-94.6998 201.147,-94.6998 213.147,-106.7 213.147,-191.3 201.147,-203.3"></polygon>
<path fill="white" stroke="white" d="M90.8526,-203.3C84.8526,-203.3 78.8526,-197.3 78.8526,-191.3"></path>
<path fill="white" stroke="white" d="M78.8526,-106.7C78.8526,-100.7 84.8526,-94.6998 90.8526,-94.6998"></path>
<path fill="white" stroke="white" d="M201.147,-94.6998C207.147,-94.6998 213.147,-100.7 213.147,-106.7"></path>
<path fill="white" stroke="white" d="M213.147,-191.3C213.147,-197.3 207.147,-203.3 201.147,-203.3"></path>
<polyline fill="none" stroke="black" points="201.147,-203.3 90.8526,-203.3 "></polyline>
<path fill="none" stroke="black" d="M90.8526,-203.3C84.8526,-203.3 78.8526,-197.3 78.8526,-191.3"></path>
<polyline fill="none" stroke="black" points="78.8526,-191.3 78.8526,-106.7 "></polyline>
<path fill="none" stroke="black" d="M78.8526,-106.7C78.8526,-100.7 84.8526,-94.6998 90.8526,-94.6998"></path>
<polyline fill="none" stroke="black" points="90.8526,-94.6998 201.147,-94.6998 "></polyline>
<path fill="none" stroke="black" d="M201.147,-94.6998C207.147,-94.6998 213.147,-100.7 213.147,-106.7"></path>
<polyline fill="none" stroke="black" points="213.147,-106.7 213.147,-191.3 "></polyline>
<path fill="none" stroke="black" d="M213.147,-191.3C213.147,-197.3 207.147,-203.3 201.147,-203.3"></path>
<text text-anchor="middle" x="146" y="-186.8" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="146" y="-170" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="146" y="-153.2" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="146" y="-136.4" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="146" y="-119.6" font-family="Times,serif" font-size="14.00">IfStatement</text>
<text text-anchor="middle" x="146" y="-102.8" font-family="Times,serif" font-size="14.00">Identifier (b)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M185.449,-239.809C182.111,-232.21 177.961,-222.761 173.617,-212.872"></path>
<polygon fill="black" stroke="black" points="176.817,-211.454 169.59,-203.706 170.408,-214.269 176.817,-211.454"></polygon>
</g>
<g id="node7" class="node"><title>s1_7</title>
<polygon fill="white" stroke="white" points="388.314,-169.602 281.686,-169.602 269.686,-157.602 269.686,-140.398 281.686,-128.398 388.314,-128.398 400.314,-140.398 400.314,-157.602 388.314,-169.602"></polygon>
<path fill="white" stroke="white" d="M281.686,-169.602C275.686,-169.602 269.686,-163.602 269.686,-157.602"></path>
<path fill="white" stroke="white" d="M269.686,-140.398C269.686,-134.398 275.686,-128.398 281.686,-128.398"></path>
<path fill="white" stroke="white" d="M388.314,-128.398C394.314,-128.398 400.314,-134.398 400.314,-140.398"></path>
<path fill="white" stroke="white" d="M400.314,-157.602C400.314,-163.602 394.314,-169.602 388.314,-169.602"></path>
<polyline fill="none" stroke="black" points="388.314,-169.602 281.686,-169.602 "></polyline>
<path fill="none" stroke="black" d="M281.686,-169.602C275.686,-169.602 269.686,-163.602 269.686,-157.602"></path>
<polyline fill="none" stroke="black" points="269.686,-157.602 269.686,-140.398 "></polyline>
<path fill="none" stroke="black" d="M269.686,-140.398C269.686,-134.398 275.686,-128.398 281.686,-128.398"></path>
<polyline fill="none" stroke="black" points="281.686,-128.398 388.314,-128.398 "></polyline>
<path fill="none" stroke="black" d="M388.314,-128.398C394.314,-128.398 400.314,-134.398 400.314,-140.398"></path>
<polyline fill="none" stroke="black" points="400.314,-140.398 400.314,-157.602 "></polyline>
<path fill="none" stroke="black" d="M400.314,-157.602C400.314,-163.602 394.314,-169.602 388.314,-169.602"></path>
<text text-anchor="middle" x="335" y="-153.2" font-family="Times,serif" font-size="14.00">WhileStatement:exit</text>
<text text-anchor="middle" x="335" y="-136.4" font-family="Times,serif" font-size="14.00">Program:exit</text>
</g>
<g id="edge7" class="edge"><title>s1_2-&gt;s1_7</title>
<path fill="none" stroke="black" d="M215.815,-239.809C238.735,-222.537 274.341,-195.708 300.672,-175.867"></path>
<polygon fill="black" stroke="black" points="302.987,-178.505 308.867,-169.692 298.774,-172.914 302.987,-178.505"></polygon>
</g>
<g id="node6" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="110.49,-49.6019 11.5095,-49.6019 -0.490457,-37.6019 -0.490457,-20.3981 11.5095,-8.3981 110.49,-8.3981 122.49,-20.3981 122.49,-37.6019 110.49,-49.6019"></polygon>
<path fill="white" stroke="white" d="M11.5095,-49.6019C5.50954,-49.6019 -0.490457,-43.6019 -0.490457,-37.6019"></path>
<path fill="white" stroke="white" d="M-0.490457,-20.3981C-0.490457,-14.3981 5.50954,-8.3981 11.5095,-8.3981"></path>
<path fill="white" stroke="white" d="M110.49,-8.3981C116.49,-8.3981 122.49,-14.3981 122.49,-20.3981"></path>
<path fill="white" stroke="white" d="M122.49,-37.6019C122.49,-43.6019 116.49,-49.6019 110.49,-49.6019"></path>
<polyline fill="none" stroke="black" points="110.49,-49.6019 11.5095,-49.6019 "></polyline>
<path fill="none" stroke="black" d="M11.5095,-49.6019C5.50954,-49.6019 -0.490457,-43.6019 -0.490457,-37.6019"></path>
<polyline fill="none" stroke="black" points="-0.490457,-37.6019 -0.490457,-20.3981 "></polyline>
<path fill="none" stroke="black" d="M-0.490457,-20.3981C-0.490457,-14.3981 5.50954,-8.3981 11.5095,-8.3981"></path>
<polyline fill="none" stroke="black" points="11.5095,-8.3981 110.49,-8.3981 "></polyline>
<path fill="none" stroke="black" d="M110.49,-8.3981C116.49,-8.3981 122.49,-14.3981 122.49,-20.3981"></path>
<polyline fill="none" stroke="black" points="122.49,-20.3981 122.49,-37.6019 "></polyline>
<path fill="none" stroke="black" d="M122.49,-37.6019C122.49,-43.6019 116.49,-49.6019 110.49,-49.6019"></path>
<text text-anchor="middle" x="61" y="-33.2" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="61" y="-16.4" font-family="Times,serif" font-size="14.00">ContinueStatement</text>
</g>
<g id="edge5" class="edge"><title>s1_3-&gt;s1_4</title>
<path fill="none" stroke="black" d="M107.479,-94.524C98.3982,-81.9176 89.0729,-68.9717 81.181,-58.0159"></path>
<polygon fill="black" stroke="black" points="83.876,-55.7691 75.1912,-49.7007 78.1962,-59.8605 83.876,-55.7691"></polygon>
</g>
<g id="node8" class="node"><title>s1_6</title>
<polygon fill="white" stroke="white" points="282.147,-58.4014 171.853,-58.4014 159.853,-46.4014 159.853,-11.5986 171.853,0.401379 282.147,0.401379 294.147,-11.5986 294.147,-46.4014 282.147,-58.4014"></polygon>
<path fill="white" stroke="white" d="M171.853,-58.4014C165.853,-58.4014 159.853,-52.4014 159.853,-46.4014"></path>
<path fill="white" stroke="white" d="M159.853,-11.5986C159.853,-5.59862 165.853,0.401379 171.853,0.401379"></path>
<path fill="white" stroke="white" d="M282.147,0.401379C288.147,0.401379 294.147,-5.59862 294.147,-11.5986"></path>
<path fill="white" stroke="white" d="M294.147,-46.4014C294.147,-52.4014 288.147,-58.4014 282.147,-58.4014"></path>
<polyline fill="none" stroke="black" points="282.147,-58.4014 171.853,-58.4014 "></polyline>
<path fill="none" stroke="black" d="M171.853,-58.4014C165.853,-58.4014 159.853,-52.4014 159.853,-46.4014"></path>
<polyline fill="none" stroke="black" points="159.853,-46.4014 159.853,-11.5986 "></polyline>
<path fill="none" stroke="black" d="M159.853,-11.5986C159.853,-5.59862 165.853,0.401379 171.853,0.401379"></path>
<polyline fill="none" stroke="black" points="171.853,0.401379 282.147,0.401379 "></polyline>
<path fill="none" stroke="black" d="M282.147,0.401379C288.147,0.401379 294.147,-5.59862 294.147,-11.5986"></path>
<polyline fill="none" stroke="black" points="294.147,-11.5986 294.147,-46.4014 "></polyline>
<path fill="none" stroke="black" d="M294.147,-46.4014C294.147,-52.4014 288.147,-58.4014 282.147,-58.4014"></path>
<text text-anchor="middle" x="227" y="-41.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="227" y="-24.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="227" y="-8" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge9" class="edge"><title>s1_3-&gt;s1_6</title>
<path fill="none" stroke="black" d="M182.708,-94.524C189.112,-85.1942 195.644,-75.6786 201.656,-66.9212"></path>
<polygon fill="black" stroke="black" points="204.696,-68.677 207.47,-58.4517 198.925,-64.7154 204.696,-68.677"></polygon>
</g>
<g id="edge6" class="edge"><title>s1_4-&gt;s1_2</title>
<path fill="none" stroke="black" d="M55.8178,-49.8729C48.0052,-84.5943 37.3518,-157.069 70,-204 86.0013,-227.001 114.192,-240.092 139.552,-247.506"></path>
<polygon fill="black" stroke="black" points="138.9,-250.955 149.466,-250.168 140.715,-244.194 138.9,-250.955"></polygon>
</g>
<g id="edge12" class="edge"><title>s1_7-&gt;final</title>
<path fill="none" stroke="black" d="M335,-128.249C335,-107.258 335,-74.136 335,-52.2408"></path>
<polygon fill="black" stroke="black" points="338.5,-52.2172 335,-42.2173 331.5,-52.2173 338.5,-52.2172"></polygon>
</g>
<g id="edge10" class="edge"><title>s1_6-&gt;s1_2</title>
<path fill="none" stroke="black" d="M230.184,-58.3131C233.209,-93.2424 235.52,-154.122 222,-204 219.488,-213.268 215.064,-222.685 210.417,-230.959"></path>
<polygon fill="black" stroke="black" points="207.291,-229.367 205.165,-239.747 213.299,-232.958 207.291,-229.367"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,113 @@
<?xml version="1.0"?>
<svg width="238pt" height="478pt" viewBox="0.00 0.00 238.00 478.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 474)">
<title>Code Path 1</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="164" cy="-461" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="212.228,-415.7 115.772,-415.7 103.772,-403.7 103.772,-352.3 115.772,-340.3 212.228,-340.3 224.228,-352.3 224.228,-403.7 212.228,-415.7"></polygon>
<path fill="white" stroke="white" d="M115.772,-415.7C109.772,-415.7 103.772,-409.7 103.772,-403.7"></path>
<path fill="white" stroke="white" d="M103.772,-352.3C103.772,-346.3 109.772,-340.3 115.772,-340.3"></path>
<path fill="white" stroke="white" d="M212.228,-340.3C218.228,-340.3 224.228,-346.3 224.228,-352.3"></path>
<path fill="white" stroke="white" d="M224.228,-403.7C224.228,-409.7 218.228,-415.7 212.228,-415.7"></path>
<polyline fill="none" stroke="black" points="212.228,-415.7 115.772,-415.7 "></polyline>
<path fill="none" stroke="black" d="M115.772,-415.7C109.772,-415.7 103.772,-409.7 103.772,-403.7"></path>
<polyline fill="none" stroke="black" points="103.772,-403.7 103.772,-352.3 "></polyline>
<path fill="none" stroke="black" d="M103.772,-352.3C103.772,-346.3 109.772,-340.3 115.772,-340.3"></path>
<polyline fill="none" stroke="black" points="115.772,-340.3 212.228,-340.3 "></polyline>
<path fill="none" stroke="black" d="M212.228,-340.3C218.228,-340.3 224.228,-346.3 224.228,-352.3"></path>
<polyline fill="none" stroke="black" points="224.228,-352.3 224.228,-403.7 "></polyline>
<path fill="none" stroke="black" d="M224.228,-403.7C224.228,-409.7 218.228,-415.7 212.228,-415.7"></path>
<text text-anchor="middle" x="164" y="-399" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="164" y="-382.2" font-family="Times,serif" font-size="14.00">IfStatement</text>
<text text-anchor="middle" x="164" y="-365.4" font-family="Times,serif" font-size="14.00">LogicalExpression</text>
<text text-anchor="middle" x="164" y="-348.6" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M164,-451.937C164,-445.515 164,-435.952 164,-425.848"></path>
<polygon fill="black" stroke="black" points="167.5,-425.66 164,-415.66 160.5,-425.66 167.5,-425.66"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="162" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="162" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="159.429,-304 96.5714,-304 84.5714,-292 84.5714,-280 96.5714,-268 159.429,-268 171.429,-280 171.429,-292 159.429,-304"></polygon>
<path fill="white" stroke="white" d="M96.5714,-304C90.5714,-304 84.5714,-298 84.5714,-292"></path>
<path fill="white" stroke="white" d="M84.5714,-280C84.5714,-274 90.5714,-268 96.5714,-268"></path>
<path fill="white" stroke="white" d="M159.429,-268C165.429,-268 171.429,-274 171.429,-280"></path>
<path fill="white" stroke="white" d="M171.429,-292C171.429,-298 165.429,-304 159.429,-304"></path>
<polyline fill="none" stroke="black" points="159.429,-304 96.5714,-304 "></polyline>
<path fill="none" stroke="black" d="M96.5714,-304C90.5714,-304 84.5714,-298 84.5714,-292"></path>
<polyline fill="none" stroke="black" points="84.5714,-292 84.5714,-280 "></polyline>
<path fill="none" stroke="black" d="M84.5714,-280C84.5714,-274 90.5714,-268 96.5714,-268"></path>
<polyline fill="none" stroke="black" points="96.5714,-268 159.429,-268 "></polyline>
<path fill="none" stroke="black" d="M159.429,-268C165.429,-268 171.429,-274 171.429,-280"></path>
<polyline fill="none" stroke="black" points="171.429,-280 171.429,-292 "></polyline>
<path fill="none" stroke="black" d="M171.429,-292C171.429,-298 165.429,-304 159.429,-304"></path>
<text text-anchor="middle" x="128" y="-281.8" font-family="Times,serif" font-size="14.00">Identifier (b)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M149.357,-340.394C145.815,-331.536 142.092,-322.229 138.765,-313.912"></path>
<polygon fill="black" stroke="black" points="141.905,-312.338 134.941,-304.353 135.405,-314.938 141.905,-312.338"></polygon>
</g>
<g id="node6" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="217.147,-120.401 106.853,-120.401 94.8526,-108.401 94.8526,-73.5986 106.853,-61.5986 217.147,-61.5986 229.147,-73.5986 229.147,-108.401 217.147,-120.401"></polygon>
<path fill="white" stroke="white" d="M106.853,-120.401C100.853,-120.401 94.8526,-114.401 94.8526,-108.401"></path>
<path fill="white" stroke="white" d="M94.8526,-73.5986C94.8526,-67.5986 100.853,-61.5986 106.853,-61.5986"></path>
<path fill="white" stroke="white" d="M217.147,-61.5986C223.147,-61.5986 229.147,-67.5986 229.147,-73.5986"></path>
<path fill="white" stroke="white" d="M229.147,-108.401C229.147,-114.401 223.147,-120.401 217.147,-120.401"></path>
<polyline fill="none" stroke="black" points="217.147,-120.401 106.853,-120.401 "></polyline>
<path fill="none" stroke="black" d="M106.853,-120.401C100.853,-120.401 94.8526,-114.401 94.8526,-108.401"></path>
<polyline fill="none" stroke="black" points="94.8526,-108.401 94.8526,-73.5986 "></polyline>
<path fill="none" stroke="black" d="M94.8526,-73.5986C94.8526,-67.5986 100.853,-61.5986 106.853,-61.5986"></path>
<polyline fill="none" stroke="black" points="106.853,-61.5986 217.147,-61.5986 "></polyline>
<path fill="none" stroke="black" d="M217.147,-61.5986C223.147,-61.5986 229.147,-67.5986 229.147,-73.5986"></path>
<polyline fill="none" stroke="black" points="229.147,-73.5986 229.147,-108.401 "></polyline>
<path fill="none" stroke="black" d="M229.147,-108.401C229.147,-114.401 223.147,-120.401 217.147,-120.401"></path>
<text text-anchor="middle" x="162" y="-103.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="162" y="-86.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="162" y="-70" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge7" class="edge"><title>s1_1-&gt;s1_4</title>
<path fill="none" stroke="black" d="M173.704,-340.118C176.287,-328.633 178.715,-315.867 180,-304 186.559,-243.442 177.199,-172.935 169.707,-130.425"></path>
<polygon fill="black" stroke="black" points="173.135,-129.714 167.902,-120.501 166.248,-130.966 173.135,-129.714"></polygon>
</g>
<g id="node5" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="122.147,-231.7 11.8526,-231.7 -0.147372,-219.7 -0.147372,-168.3 11.8526,-156.3 122.147,-156.3 134.147,-168.3 134.147,-219.7 122.147,-231.7"></polygon>
<path fill="white" stroke="white" d="M11.8526,-231.7C5.85263,-231.7 -0.147372,-225.7 -0.147372,-219.7"></path>
<path fill="white" stroke="white" d="M-0.147372,-168.3C-0.147372,-162.3 5.85263,-156.3 11.8526,-156.3"></path>
<path fill="white" stroke="white" d="M122.147,-156.3C128.147,-156.3 134.147,-162.3 134.147,-168.3"></path>
<path fill="white" stroke="white" d="M134.147,-219.7C134.147,-225.7 128.147,-231.7 122.147,-231.7"></path>
<polyline fill="none" stroke="black" points="122.147,-231.7 11.8526,-231.7 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-231.7C5.85263,-231.7 -0.147372,-225.7 -0.147372,-219.7"></path>
<polyline fill="none" stroke="black" points="-0.147372,-219.7 -0.147372,-168.3 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-168.3C-0.147372,-162.3 5.85263,-156.3 11.8526,-156.3"></path>
<polyline fill="none" stroke="black" points="11.8526,-156.3 122.147,-156.3 "></polyline>
<path fill="none" stroke="black" d="M122.147,-156.3C128.147,-156.3 134.147,-162.3 134.147,-168.3"></path>
<polyline fill="none" stroke="black" points="134.147,-168.3 134.147,-219.7 "></polyline>
<path fill="none" stroke="black" d="M134.147,-219.7C134.147,-225.7 128.147,-231.7 122.147,-231.7"></path>
<text text-anchor="middle" x="67" y="-215" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-198.2" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-181.4" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-164.6" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M116.239,-267.647C110.883,-259.746 104.269,-249.988 97.6462,-240.216"></path>
<polygon fill="black" stroke="black" points="100.363,-237.985 91.855,-231.671 94.5683,-241.913 100.363,-237.985"></polygon>
</g>
<g id="edge9" class="edge"><title>s1_2-&gt;s1_4</title>
<path fill="none" stroke="black" d="M133.482,-267.966C136.637,-257.648 140.465,-244.17 143,-232 150.074,-198.038 155.131,-158.871 158.24,-130.616"></path>
<polygon fill="black" stroke="black" points="161.754,-130.67 159.337,-120.355 154.794,-129.926 161.754,-130.67"></polygon>
</g>
<g id="edge5" class="edge"><title>s1_3-&gt;s1_4</title>
<path fill="none" stroke="black" d="M101.566,-156.251C110.27,-146.997 119.601,-137.077 128.264,-127.867"></path>
<polygon fill="black" stroke="black" points="131.053,-130.01 135.355,-120.328 125.954,-125.214 131.053,-130.01"></polygon>
</g>
<g id="edge10" class="edge"><title>s1_4-&gt;final</title>
<path fill="none" stroke="black" d="M162,-61.7004C162,-53.2282 162,-44.0665 162,-36.0585"></path>
<polygon fill="black" stroke="black" points="165.5,-36.0267 162,-26.0267 158.5,-36.0267 165.5,-36.0267"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -0,0 +1,84 @@
<?xml version="1.0"?>
<svg width="136pt" height="344pt" viewBox="0.00 0.00 136.00 344.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 340)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="64" cy="-327" rx="9" ry="9"></ellipse>
</g>
<g id="node2" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="116.617,-281.3 11.3833,-281.3 -0.616716,-269.3 -0.616716,-184.7 11.3833,-172.7 116.617,-172.7 128.617,-184.7 128.617,-269.3 116.617,-281.3"></polygon>
<path fill="white" stroke="white" d="M11.3833,-281.3C5.38328,-281.3 -0.616716,-275.3 -0.616716,-269.3"></path>
<path fill="white" stroke="white" d="M-0.616716,-184.7C-0.616716,-178.7 5.38328,-172.7 11.3833,-172.7"></path>
<path fill="white" stroke="white" d="M116.617,-172.7C122.617,-172.7 128.617,-178.7 128.617,-184.7"></path>
<path fill="white" stroke="white" d="M128.617,-269.3C128.617,-275.3 122.617,-281.3 116.617,-281.3"></path>
<polyline fill="none" stroke="black" points="116.617,-281.3 11.3833,-281.3 "></polyline>
<path fill="none" stroke="black" d="M11.3833,-281.3C5.38328,-281.3 -0.616716,-275.3 -0.616716,-269.3"></path>
<polyline fill="none" stroke="black" points="-0.616716,-269.3 -0.616716,-184.7 "></polyline>
<path fill="none" stroke="black" d="M-0.616716,-184.7C-0.616716,-178.7 5.38328,-172.7 11.3833,-172.7"></path>
<polyline fill="none" stroke="black" points="11.3833,-172.7 116.617,-172.7 "></polyline>
<path fill="none" stroke="black" d="M116.617,-172.7C122.617,-172.7 128.617,-178.7 128.617,-184.7"></path>
<polyline fill="none" stroke="black" points="128.617,-184.7 128.617,-269.3 "></polyline>
<path fill="none" stroke="black" d="M128.617,-269.3C128.617,-275.3 122.617,-281.3 116.617,-281.3"></path>
<text text-anchor="middle" x="64" y="-264.8" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="64" y="-248" font-family="Times,serif" font-size="14.00">ForStatement</text>
<text text-anchor="middle" x="64" y="-231.2" font-family="Times,serif" font-size="14.00">VariableDeclaration</text>
<text text-anchor="middle" x="64" y="-214.4" font-family="Times,serif" font-size="14.00">VariableDeclarator</text>
<text text-anchor="middle" x="64" y="-197.6" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="64" y="-180.8" font-family="Times,serif" font-size="14.00">Literal (0)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M64,-317.98C64,-311.675 64,-302.238 64,-291.813"></path>
<polygon fill="black" stroke="black" points="67.5001,-291.586 64,-281.586 60.5001,-291.586 67.5001,-291.586"></polygon>
</g>
<g id="node3" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="110.233,-136.401 17.7673,-136.401 5.76729,-124.401 5.76729,-89.5986 17.7673,-77.5986 110.233,-77.5986 122.233,-89.5986 122.233,-124.401 110.233,-136.401"></polygon>
<path fill="white" stroke="white" d="M17.7673,-136.401C11.7673,-136.401 5.76729,-130.401 5.76729,-124.401"></path>
<path fill="white" stroke="white" d="M5.76729,-89.5986C5.76729,-83.5986 11.7673,-77.5986 17.7673,-77.5986"></path>
<path fill="white" stroke="white" d="M110.233,-77.5986C116.233,-77.5986 122.233,-83.5986 122.233,-89.5986"></path>
<path fill="white" stroke="white" d="M122.233,-124.401C122.233,-130.401 116.233,-136.401 110.233,-136.401"></path>
<polyline fill="none" stroke="black" points="110.233,-136.401 17.7673,-136.401 "></polyline>
<path fill="none" stroke="black" d="M17.7673,-136.401C11.7673,-136.401 5.76729,-130.401 5.76729,-124.401"></path>
<polyline fill="none" stroke="black" points="5.76729,-124.401 5.76729,-89.5986 "></polyline>
<path fill="none" stroke="black" d="M5.76729,-89.5986C5.76729,-83.5986 11.7673,-77.5986 17.7673,-77.5986"></path>
<polyline fill="none" stroke="black" points="17.7673,-77.5986 110.233,-77.5986 "></polyline>
<path fill="none" stroke="black" d="M110.233,-77.5986C116.233,-77.5986 122.233,-83.5986 122.233,-89.5986"></path>
<polyline fill="none" stroke="black" points="122.233,-89.5986 122.233,-124.401 "></polyline>
<path fill="none" stroke="black" d="M122.233,-124.401C122.233,-130.401 116.233,-136.401 110.233,-136.401"></path>
<text text-anchor="middle" x="64" y="-119.6" font-family="Times,serif" font-size="14.00">BinaryExpression</text>
<text text-anchor="middle" x="64" y="-102.8" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="64" y="-86" font-family="Times,serif" font-size="14.00">Literal (10)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M64,-172.524C64,-163.777 64,-154.867 64,-146.572"></path>
<polygon fill="black" stroke="black" points="67.5001,-146.452 64,-136.452 60.5001,-146.452 67.5001,-146.452"></polygon>
</g>
<g id="node4" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="110.977,-41.6019 17.0234,-41.6019 5.02345,-29.6019 5.02345,-12.3981 17.0234,-0.398095 110.977,-0.398095 122.977,-12.3981 122.977,-29.6019 110.977,-41.6019"></polygon>
<path fill="white" stroke="white" d="M17.0234,-41.6019C11.0234,-41.6019 5.02345,-35.6019 5.02345,-29.6019"></path>
<path fill="white" stroke="white" d="M5.02345,-12.3981C5.02345,-6.3981 11.0234,-0.398095 17.0234,-0.398095"></path>
<path fill="white" stroke="white" d="M110.977,-0.398095C116.977,-0.398095 122.977,-6.3981 122.977,-12.3981"></path>
<path fill="white" stroke="white" d="M122.977,-29.6019C122.977,-35.6019 116.977,-41.6019 110.977,-41.6019"></path>
<polyline fill="none" stroke="black" points="110.977,-41.6019 17.0234,-41.6019 "></polyline>
<path fill="none" stroke="black" d="M17.0234,-41.6019C11.0234,-41.6019 5.02345,-35.6019 5.02345,-29.6019"></path>
<polyline fill="none" stroke="black" points="5.02345,-29.6019 5.02345,-12.3981 "></polyline>
<path fill="none" stroke="black" d="M5.02345,-12.3981C5.02345,-6.3981 11.0234,-0.398095 17.0234,-0.398095"></path>
<polyline fill="none" stroke="black" points="17.0234,-0.398095 110.977,-0.398095 "></polyline>
<path fill="none" stroke="black" d="M110.977,-0.398095C116.977,-0.398095 122.977,-6.3981 122.977,-12.3981"></path>
<polyline fill="none" stroke="black" points="122.977,-12.3981 122.977,-29.6019 "></polyline>
<path fill="none" stroke="black" d="M122.977,-29.6019C122.977,-35.6019 116.977,-41.6019 110.977,-41.6019"></path>
<text text-anchor="middle" x="64" y="-25.2" font-family="Times,serif" font-size="14.00">UpdateExpression</text>
<text text-anchor="middle" x="64" y="-8.4" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
</g>
<g id="edge5" class="edge"><title>s1_2-&gt;s1_4</title>
<path fill="none" stroke="none" d="M64,-77.5614C64,-69.2619 64,-60.1709 64,-51.7903"></path>
<polygon fill="none" stroke="none" points="67.5001,-51.6677 64,-41.6677 60.5001,-51.6678 67.5001,-51.6677"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1,110 @@
<?xml version="1.0"?>
<svg width="278pt" height="394pt" viewBox="0.00 0.00 278.00 394.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 390)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="139" cy="-377" rx="9" ry="9"></ellipse>
</g>
<g id="node2" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="191.617,-331.3 86.3833,-331.3 74.3833,-319.3 74.3833,-234.7 86.3833,-222.7 191.617,-222.7 203.617,-234.7 203.617,-319.3 191.617,-331.3"></polygon>
<path fill="white" stroke="white" d="M86.3833,-331.3C80.3833,-331.3 74.3833,-325.3 74.3833,-319.3"></path>
<path fill="white" stroke="white" d="M74.3833,-234.7C74.3833,-228.7 80.3833,-222.7 86.3833,-222.7"></path>
<path fill="white" stroke="white" d="M191.617,-222.7C197.617,-222.7 203.617,-228.7 203.617,-234.7"></path>
<path fill="white" stroke="white" d="M203.617,-319.3C203.617,-325.3 197.617,-331.3 191.617,-331.3"></path>
<polyline fill="none" stroke="black" points="191.617,-331.3 86.3833,-331.3 "></polyline>
<path fill="none" stroke="black" d="M86.3833,-331.3C80.3833,-331.3 74.3833,-325.3 74.3833,-319.3"></path>
<polyline fill="none" stroke="black" points="74.3833,-319.3 74.3833,-234.7 "></polyline>
<path fill="none" stroke="black" d="M74.3833,-234.7C74.3833,-228.7 80.3833,-222.7 86.3833,-222.7"></path>
<polyline fill="none" stroke="black" points="86.3833,-222.7 191.617,-222.7 "></polyline>
<path fill="none" stroke="black" d="M191.617,-222.7C197.617,-222.7 203.617,-228.7 203.617,-234.7"></path>
<polyline fill="none" stroke="black" points="203.617,-234.7 203.617,-319.3 "></polyline>
<path fill="none" stroke="black" d="M203.617,-319.3C203.617,-325.3 197.617,-331.3 191.617,-331.3"></path>
<text text-anchor="middle" x="139" y="-314.8" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="139" y="-298" font-family="Times,serif" font-size="14.00">ForStatement</text>
<text text-anchor="middle" x="139" y="-281.2" font-family="Times,serif" font-size="14.00">VariableDeclaration</text>
<text text-anchor="middle" x="139" y="-264.4" font-family="Times,serif" font-size="14.00">VariableDeclarator</text>
<text text-anchor="middle" x="139" y="-247.6" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="139" y="-230.8" font-family="Times,serif" font-size="14.00">Literal (0)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M139,-367.98C139,-361.675 139,-352.238 139,-341.813"></path>
<polygon fill="black" stroke="black" points="142.5,-341.586 139,-331.586 135.5,-341.586 142.5,-341.586"></polygon>
</g>
<g id="node3" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="185.233,-186.401 92.7673,-186.401 80.7673,-174.401 80.7673,-139.599 92.7673,-127.599 185.233,-127.599 197.233,-139.599 197.233,-174.401 185.233,-186.401"></polygon>
<path fill="white" stroke="white" d="M92.7673,-186.401C86.7673,-186.401 80.7673,-180.401 80.7673,-174.401"></path>
<path fill="white" stroke="white" d="M80.7673,-139.599C80.7673,-133.599 86.7673,-127.599 92.7673,-127.599"></path>
<path fill="white" stroke="white" d="M185.233,-127.599C191.233,-127.599 197.233,-133.599 197.233,-139.599"></path>
<path fill="white" stroke="white" d="M197.233,-174.401C197.233,-180.401 191.233,-186.401 185.233,-186.401"></path>
<polyline fill="none" stroke="black" points="185.233,-186.401 92.7673,-186.401 "></polyline>
<path fill="none" stroke="black" d="M92.7673,-186.401C86.7673,-186.401 80.7673,-180.401 80.7673,-174.401"></path>
<polyline fill="none" stroke="black" points="80.7673,-174.401 80.7673,-139.599 "></polyline>
<path fill="none" stroke="black" d="M80.7673,-139.599C80.7673,-133.599 86.7673,-127.599 92.7673,-127.599"></path>
<polyline fill="none" stroke="black" points="92.7673,-127.599 185.233,-127.599 "></polyline>
<path fill="none" stroke="black" d="M185.233,-127.599C191.233,-127.599 197.233,-133.599 197.233,-139.599"></path>
<polyline fill="none" stroke="black" points="197.233,-139.599 197.233,-174.401 "></polyline>
<path fill="none" stroke="black" d="M197.233,-174.401C197.233,-180.401 191.233,-186.401 185.233,-186.401"></path>
<text text-anchor="middle" x="139" y="-169.6" font-family="Times,serif" font-size="14.00">BinaryExpression</text>
<text text-anchor="middle" x="139" y="-152.8" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="139" y="-136" font-family="Times,serif" font-size="14.00">Literal (10)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M139,-222.524C139,-213.777 139,-204.867 139,-196.572"></path>
<polygon fill="black" stroke="black" points="142.5,-196.452 139,-186.452 135.5,-196.452 142.5,-196.452"></polygon>
</g>
<g id="node4" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="122.147,-92 11.8526,-92 -0.147372,-80 -0.147372,-12 11.8526,0 122.147,0 134.147,-12 134.147,-80 122.147,-92"></polygon>
<path fill="white" stroke="white" d="M11.8526,-92C5.85263,-92 -0.147372,-86 -0.147372,-80"></path>
<path fill="white" stroke="white" d="M-0.147372,-12C-0.147372,-6 5.85263,0 11.8526,0"></path>
<path fill="white" stroke="white" d="M122.147,0C128.147,0 134.147,-6 134.147,-12"></path>
<path fill="white" stroke="white" d="M134.147,-80C134.147,-86 128.147,-92 122.147,-92"></path>
<polyline fill="none" stroke="black" points="122.147,-92 11.8526,-92 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-92C5.85263,-92 -0.147372,-86 -0.147372,-80"></path>
<polyline fill="none" stroke="black" points="-0.147372,-80 -0.147372,-12 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-12C-0.147372,-6 5.85263,0 11.8526,0"></path>
<polyline fill="none" stroke="black" points="11.8526,0 122.147,0 "></polyline>
<path fill="none" stroke="black" d="M122.147,0C128.147,0 134.147,-6 134.147,-12"></path>
<polyline fill="none" stroke="black" points="134.147,-12 134.147,-80 "></polyline>
<path fill="none" stroke="black" d="M134.147,-80C134.147,-86 128.147,-92 122.147,-92"></path>
<text text-anchor="middle" x="67" y="-75.4" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-58.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-41.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-25" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="67" y="-8.2" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M120.271,-127.646C114.784,-119.339 108.595,-109.971 102.429,-100.636"></path>
<polygon fill="black" stroke="black" points="105.226,-98.519 96.7935,-92.1041 99.3848,-102.377 105.226,-98.519"></polygon>
</g>
<g id="node5" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="257.977,-66.6019 164.023,-66.6019 152.023,-54.6019 152.023,-37.3981 164.023,-25.3981 257.977,-25.3981 269.977,-37.3981 269.977,-54.6019 257.977,-66.6019"></polygon>
<path fill="white" stroke="white" d="M164.023,-66.6019C158.023,-66.6019 152.023,-60.6019 152.023,-54.6019"></path>
<path fill="white" stroke="white" d="M152.023,-37.3981C152.023,-31.3981 158.023,-25.3981 164.023,-25.3981"></path>
<path fill="white" stroke="white" d="M257.977,-25.3981C263.977,-25.3981 269.977,-31.3981 269.977,-37.3981"></path>
<path fill="white" stroke="white" d="M269.977,-54.6019C269.977,-60.6019 263.977,-66.6019 257.977,-66.6019"></path>
<polyline fill="none" stroke="black" points="257.977,-66.6019 164.023,-66.6019 "></polyline>
<path fill="none" stroke="black" d="M164.023,-66.6019C158.023,-66.6019 152.023,-60.6019 152.023,-54.6019"></path>
<polyline fill="none" stroke="black" points="152.023,-54.6019 152.023,-37.3981 "></polyline>
<path fill="none" stroke="black" d="M152.023,-37.3981C152.023,-31.3981 158.023,-25.3981 164.023,-25.3981"></path>
<polyline fill="none" stroke="black" points="164.023,-25.3981 257.977,-25.3981 "></polyline>
<path fill="none" stroke="black" d="M257.977,-25.3981C263.977,-25.3981 269.977,-31.3981 269.977,-37.3981"></path>
<polyline fill="none" stroke="black" points="269.977,-37.3981 269.977,-54.6019 "></polyline>
<path fill="none" stroke="black" d="M269.977,-54.6019C269.977,-60.6019 263.977,-66.6019 257.977,-66.6019"></path>
<text text-anchor="middle" x="211" y="-50.2" font-family="Times,serif" font-size="14.00">UpdateExpression</text>
<text text-anchor="middle" x="211" y="-33.4" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
</g>
<g id="edge6" class="edge"><title>s1_2-&gt;s1_4</title>
<path fill="none" stroke="none" d="M157.729,-127.646C168.417,-111.466 181.766,-91.2577 192.427,-75.1175"></path>
<polygon fill="none" stroke="none" points="195.448,-76.8939 198.039,-66.6208 189.607,-73.0357 195.448,-76.8939"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -0,0 +1,115 @@
<?xml version="1.0"?>
<svg width="186pt" height="472pt" viewBox="0.00 0.00 186.00 472.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 468)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="114" cy="-455" rx="9" ry="9"></ellipse>
</g>
<g id="node2" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="166.617,-409.3 61.3833,-409.3 49.3833,-397.3 49.3833,-312.7 61.3833,-300.7 166.617,-300.7 178.617,-312.7 178.617,-397.3 166.617,-409.3"></polygon>
<path fill="white" stroke="white" d="M61.3833,-409.3C55.3833,-409.3 49.3833,-403.3 49.3833,-397.3"></path>
<path fill="white" stroke="white" d="M49.3833,-312.7C49.3833,-306.7 55.3833,-300.7 61.3833,-300.7"></path>
<path fill="white" stroke="white" d="M166.617,-300.7C172.617,-300.7 178.617,-306.7 178.617,-312.7"></path>
<path fill="white" stroke="white" d="M178.617,-397.3C178.617,-403.3 172.617,-409.3 166.617,-409.3"></path>
<polyline fill="none" stroke="black" points="166.617,-409.3 61.3833,-409.3 "></polyline>
<path fill="none" stroke="black" d="M61.3833,-409.3C55.3833,-409.3 49.3833,-403.3 49.3833,-397.3"></path>
<polyline fill="none" stroke="black" points="49.3833,-397.3 49.3833,-312.7 "></polyline>
<path fill="none" stroke="black" d="M49.3833,-312.7C49.3833,-306.7 55.3833,-300.7 61.3833,-300.7"></path>
<polyline fill="none" stroke="black" points="61.3833,-300.7 166.617,-300.7 "></polyline>
<path fill="none" stroke="black" d="M166.617,-300.7C172.617,-300.7 178.617,-306.7 178.617,-312.7"></path>
<polyline fill="none" stroke="black" points="178.617,-312.7 178.617,-397.3 "></polyline>
<path fill="none" stroke="black" d="M178.617,-397.3C178.617,-403.3 172.617,-409.3 166.617,-409.3"></path>
<text text-anchor="middle" x="114" y="-392.8" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="114" y="-376" font-family="Times,serif" font-size="14.00">ForStatement</text>
<text text-anchor="middle" x="114" y="-359.2" font-family="Times,serif" font-size="14.00">VariableDeclaration</text>
<text text-anchor="middle" x="114" y="-342.4" font-family="Times,serif" font-size="14.00">VariableDeclarator</text>
<text text-anchor="middle" x="114" y="-325.6" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="114" y="-308.8" font-family="Times,serif" font-size="14.00">Literal (0)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M114,-445.98C114,-439.675 114,-430.238 114,-419.813"></path>
<polygon fill="black" stroke="black" points="117.5,-419.586 114,-409.586 110.5,-419.586 117.5,-419.586"></polygon>
</g>
<g id="node3" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="160.233,-264.401 67.7673,-264.401 55.7673,-252.401 55.7673,-217.599 67.7673,-205.599 160.233,-205.599 172.233,-217.599 172.233,-252.401 160.233,-264.401"></polygon>
<path fill="white" stroke="white" d="M67.7673,-264.401C61.7673,-264.401 55.7673,-258.401 55.7673,-252.401"></path>
<path fill="white" stroke="white" d="M55.7673,-217.599C55.7673,-211.599 61.7673,-205.599 67.7673,-205.599"></path>
<path fill="white" stroke="white" d="M160.233,-205.599C166.233,-205.599 172.233,-211.599 172.233,-217.599"></path>
<path fill="white" stroke="white" d="M172.233,-252.401C172.233,-258.401 166.233,-264.401 160.233,-264.401"></path>
<polyline fill="none" stroke="black" points="160.233,-264.401 67.7673,-264.401 "></polyline>
<path fill="none" stroke="black" d="M67.7673,-264.401C61.7673,-264.401 55.7673,-258.401 55.7673,-252.401"></path>
<polyline fill="none" stroke="black" points="55.7673,-252.401 55.7673,-217.599 "></polyline>
<path fill="none" stroke="black" d="M55.7673,-217.599C55.7673,-211.599 61.7673,-205.599 67.7673,-205.599"></path>
<polyline fill="none" stroke="black" points="67.7673,-205.599 160.233,-205.599 "></polyline>
<path fill="none" stroke="black" d="M160.233,-205.599C166.233,-205.599 172.233,-211.599 172.233,-217.599"></path>
<polyline fill="none" stroke="black" points="172.233,-217.599 172.233,-252.401 "></polyline>
<path fill="none" stroke="black" d="M172.233,-252.401C172.233,-258.401 166.233,-264.401 160.233,-264.401"></path>
<text text-anchor="middle" x="114" y="-247.6" font-family="Times,serif" font-size="14.00">BinaryExpression</text>
<text text-anchor="middle" x="114" y="-230.8" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="114" y="-214" font-family="Times,serif" font-size="14.00">Literal (10)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M114,-300.524C114,-291.777 114,-282.867 114,-274.572"></path>
<polygon fill="black" stroke="black" points="117.5,-274.452 114,-264.452 110.5,-274.452 117.5,-274.452"></polygon>
</g>
<g id="node4" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="122.147,-170 11.8526,-170 -0.147372,-158 -0.147372,-90 11.8526,-78 122.147,-78 134.147,-90 134.147,-158 122.147,-170"></polygon>
<path fill="white" stroke="white" d="M11.8526,-170C5.85263,-170 -0.147372,-164 -0.147372,-158"></path>
<path fill="white" stroke="white" d="M-0.147372,-90C-0.147372,-84 5.85263,-78 11.8526,-78"></path>
<path fill="white" stroke="white" d="M122.147,-78C128.147,-78 134.147,-84 134.147,-90"></path>
<path fill="white" stroke="white" d="M134.147,-158C134.147,-164 128.147,-170 122.147,-170"></path>
<polyline fill="none" stroke="black" points="122.147,-170 11.8526,-170 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-170C5.85263,-170 -0.147372,-164 -0.147372,-158"></path>
<polyline fill="none" stroke="black" points="-0.147372,-158 -0.147372,-90 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-90C-0.147372,-84 5.85263,-78 11.8526,-78"></path>
<polyline fill="none" stroke="black" points="11.8526,-78 122.147,-78 "></polyline>
<path fill="none" stroke="black" d="M122.147,-78C128.147,-78 134.147,-84 134.147,-90"></path>
<polyline fill="none" stroke="black" points="134.147,-90 134.147,-158 "></polyline>
<path fill="none" stroke="black" d="M134.147,-158C134.147,-164 128.147,-170 122.147,-170"></path>
<text text-anchor="middle" x="67" y="-153.4" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-136.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-119.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-103" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="67" y="-86.2" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M101.774,-205.646C98.3019,-197.594 94.3994,-188.543 90.4971,-179.493"></path>
<polygon fill="black" stroke="black" points="93.6221,-177.901 86.4485,-170.104 87.1942,-180.673 93.6221,-177.901"></polygon>
</g>
<g id="node5" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="160.977,-41.6019 67.0234,-41.6019 55.0234,-29.6019 55.0234,-12.3981 67.0234,-0.398095 160.977,-0.398095 172.977,-12.3981 172.977,-29.6019 160.977,-41.6019"></polygon>
<path fill="white" stroke="white" d="M67.0234,-41.6019C61.0234,-41.6019 55.0234,-35.6019 55.0234,-29.6019"></path>
<path fill="white" stroke="white" d="M55.0234,-12.3981C55.0234,-6.3981 61.0234,-0.398095 67.0234,-0.398095"></path>
<path fill="white" stroke="white" d="M160.977,-0.398095C166.977,-0.398095 172.977,-6.3981 172.977,-12.3981"></path>
<path fill="white" stroke="white" d="M172.977,-29.6019C172.977,-35.6019 166.977,-41.6019 160.977,-41.6019"></path>
<polyline fill="none" stroke="black" points="160.977,-41.6019 67.0234,-41.6019 "></polyline>
<path fill="none" stroke="black" d="M67.0234,-41.6019C61.0234,-41.6019 55.0234,-35.6019 55.0234,-29.6019"></path>
<polyline fill="none" stroke="black" points="55.0234,-29.6019 55.0234,-12.3981 "></polyline>
<path fill="none" stroke="black" d="M55.0234,-12.3981C55.0234,-6.3981 61.0234,-0.398095 67.0234,-0.398095"></path>
<polyline fill="none" stroke="black" points="67.0234,-0.398095 160.977,-0.398095 "></polyline>
<path fill="none" stroke="black" d="M160.977,-0.398095C166.977,-0.398095 172.977,-6.3981 172.977,-12.3981"></path>
<polyline fill="none" stroke="black" points="172.977,-12.3981 172.977,-29.6019 "></polyline>
<path fill="none" stroke="black" d="M172.977,-29.6019C172.977,-35.6019 166.977,-41.6019 160.977,-41.6019"></path>
<text text-anchor="middle" x="114" y="-25.2" font-family="Times,serif" font-size="14.00">UpdateExpression</text>
<text text-anchor="middle" x="114" y="-8.4" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
</g>
<g id="edge6" class="edge"><title>s1_3-&gt;s1_4</title>
<path fill="none" stroke="red" d="M88.0256,-77.8174C92.2417,-68.7572 96.5653,-59.4661 100.445,-51.1281"></path>
<polygon fill="red" stroke="red" points="103.718,-52.392 104.763,-41.8489 97.3711,-49.4386 103.718,-52.392"></polygon>
</g>
<g id="edge8" class="edge"><title>s1_4-&gt;s1_2</title>
<path fill="none" stroke="none" d="M127.225,-41.8137C133.324,-52.1325 139.891,-65.235 143,-78 152.676,-117.727 151.633,-130.033 143,-170 141.091,-178.837 137.857,-187.92 134.226,-196.368"></path>
<polygon fill="none" stroke="none" points="130.985,-195.038 130.005,-205.588 137.35,-197.952 130.985,-195.038"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -0,0 +1,115 @@
<?xml version="1.0"?>
<svg width="186pt" height="472pt" viewBox="0.00 0.00 186.00 472.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 468)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="114" cy="-455" rx="9" ry="9"></ellipse>
</g>
<g id="node2" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="166.617,-409.3 61.3833,-409.3 49.3833,-397.3 49.3833,-312.7 61.3833,-300.7 166.617,-300.7 178.617,-312.7 178.617,-397.3 166.617,-409.3"></polygon>
<path fill="white" stroke="white" d="M61.3833,-409.3C55.3833,-409.3 49.3833,-403.3 49.3833,-397.3"></path>
<path fill="white" stroke="white" d="M49.3833,-312.7C49.3833,-306.7 55.3833,-300.7 61.3833,-300.7"></path>
<path fill="white" stroke="white" d="M166.617,-300.7C172.617,-300.7 178.617,-306.7 178.617,-312.7"></path>
<path fill="white" stroke="white" d="M178.617,-397.3C178.617,-403.3 172.617,-409.3 166.617,-409.3"></path>
<polyline fill="none" stroke="black" points="166.617,-409.3 61.3833,-409.3 "></polyline>
<path fill="none" stroke="black" d="M61.3833,-409.3C55.3833,-409.3 49.3833,-403.3 49.3833,-397.3"></path>
<polyline fill="none" stroke="black" points="49.3833,-397.3 49.3833,-312.7 "></polyline>
<path fill="none" stroke="black" d="M49.3833,-312.7C49.3833,-306.7 55.3833,-300.7 61.3833,-300.7"></path>
<polyline fill="none" stroke="black" points="61.3833,-300.7 166.617,-300.7 "></polyline>
<path fill="none" stroke="black" d="M166.617,-300.7C172.617,-300.7 178.617,-306.7 178.617,-312.7"></path>
<polyline fill="none" stroke="black" points="178.617,-312.7 178.617,-397.3 "></polyline>
<path fill="none" stroke="black" d="M178.617,-397.3C178.617,-403.3 172.617,-409.3 166.617,-409.3"></path>
<text text-anchor="middle" x="114" y="-392.8" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="114" y="-376" font-family="Times,serif" font-size="14.00">ForStatement</text>
<text text-anchor="middle" x="114" y="-359.2" font-family="Times,serif" font-size="14.00">VariableDeclaration</text>
<text text-anchor="middle" x="114" y="-342.4" font-family="Times,serif" font-size="14.00">VariableDeclarator</text>
<text text-anchor="middle" x="114" y="-325.6" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="114" y="-308.8" font-family="Times,serif" font-size="14.00">Literal (0)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M114,-445.98C114,-439.675 114,-430.238 114,-419.813"></path>
<polygon fill="black" stroke="black" points="117.5,-419.586 114,-409.586 110.5,-419.586 117.5,-419.586"></polygon>
</g>
<g id="node3" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="160.233,-264.401 67.7673,-264.401 55.7673,-252.401 55.7673,-217.599 67.7673,-205.599 160.233,-205.599 172.233,-217.599 172.233,-252.401 160.233,-264.401"></polygon>
<path fill="white" stroke="white" d="M67.7673,-264.401C61.7673,-264.401 55.7673,-258.401 55.7673,-252.401"></path>
<path fill="white" stroke="white" d="M55.7673,-217.599C55.7673,-211.599 61.7673,-205.599 67.7673,-205.599"></path>
<path fill="white" stroke="white" d="M160.233,-205.599C166.233,-205.599 172.233,-211.599 172.233,-217.599"></path>
<path fill="white" stroke="white" d="M172.233,-252.401C172.233,-258.401 166.233,-264.401 160.233,-264.401"></path>
<polyline fill="none" stroke="black" points="160.233,-264.401 67.7673,-264.401 "></polyline>
<path fill="none" stroke="black" d="M67.7673,-264.401C61.7673,-264.401 55.7673,-258.401 55.7673,-252.401"></path>
<polyline fill="none" stroke="black" points="55.7673,-252.401 55.7673,-217.599 "></polyline>
<path fill="none" stroke="black" d="M55.7673,-217.599C55.7673,-211.599 61.7673,-205.599 67.7673,-205.599"></path>
<polyline fill="none" stroke="black" points="67.7673,-205.599 160.233,-205.599 "></polyline>
<path fill="none" stroke="black" d="M160.233,-205.599C166.233,-205.599 172.233,-211.599 172.233,-217.599"></path>
<polyline fill="none" stroke="black" points="172.233,-217.599 172.233,-252.401 "></polyline>
<path fill="none" stroke="black" d="M172.233,-252.401C172.233,-258.401 166.233,-264.401 160.233,-264.401"></path>
<text text-anchor="middle" x="114" y="-247.6" font-family="Times,serif" font-size="14.00">BinaryExpression</text>
<text text-anchor="middle" x="114" y="-230.8" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="114" y="-214" font-family="Times,serif" font-size="14.00">Literal (10)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M114,-300.524C114,-291.777 114,-282.867 114,-274.572"></path>
<polygon fill="black" stroke="black" points="117.5,-274.452 114,-264.452 110.5,-274.452 117.5,-274.452"></polygon>
</g>
<g id="node4" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="122.147,-170 11.8526,-170 -0.147372,-158 -0.147372,-90 11.8526,-78 122.147,-78 134.147,-90 134.147,-158 122.147,-170"></polygon>
<path fill="white" stroke="white" d="M11.8526,-170C5.85263,-170 -0.147372,-164 -0.147372,-158"></path>
<path fill="white" stroke="white" d="M-0.147372,-90C-0.147372,-84 5.85263,-78 11.8526,-78"></path>
<path fill="white" stroke="white" d="M122.147,-78C128.147,-78 134.147,-84 134.147,-90"></path>
<path fill="white" stroke="white" d="M134.147,-158C134.147,-164 128.147,-170 122.147,-170"></path>
<polyline fill="none" stroke="black" points="122.147,-170 11.8526,-170 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-170C5.85263,-170 -0.147372,-164 -0.147372,-158"></path>
<polyline fill="none" stroke="black" points="-0.147372,-158 -0.147372,-90 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-90C-0.147372,-84 5.85263,-78 11.8526,-78"></path>
<polyline fill="none" stroke="black" points="11.8526,-78 122.147,-78 "></polyline>
<path fill="none" stroke="black" d="M122.147,-78C128.147,-78 134.147,-84 134.147,-90"></path>
<polyline fill="none" stroke="black" points="134.147,-90 134.147,-158 "></polyline>
<path fill="none" stroke="black" d="M134.147,-158C134.147,-164 128.147,-170 122.147,-170"></path>
<text text-anchor="middle" x="67" y="-153.4" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-136.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-119.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-103" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="67" y="-86.2" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M101.774,-205.646C98.3019,-197.594 94.3994,-188.543 90.4971,-179.493"></path>
<polygon fill="black" stroke="black" points="93.6221,-177.901 86.4485,-170.104 87.1942,-180.673 93.6221,-177.901"></polygon>
</g>
<g id="node5" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="160.977,-41.6019 67.0234,-41.6019 55.0234,-29.6019 55.0234,-12.3981 67.0234,-0.398095 160.977,-0.398095 172.977,-12.3981 172.977,-29.6019 160.977,-41.6019"></polygon>
<path fill="white" stroke="white" d="M67.0234,-41.6019C61.0234,-41.6019 55.0234,-35.6019 55.0234,-29.6019"></path>
<path fill="white" stroke="white" d="M55.0234,-12.3981C55.0234,-6.3981 61.0234,-0.398095 67.0234,-0.398095"></path>
<path fill="white" stroke="white" d="M160.977,-0.398095C166.977,-0.398095 172.977,-6.3981 172.977,-12.3981"></path>
<path fill="white" stroke="white" d="M172.977,-29.6019C172.977,-35.6019 166.977,-41.6019 160.977,-41.6019"></path>
<polyline fill="none" stroke="black" points="160.977,-41.6019 67.0234,-41.6019 "></polyline>
<path fill="none" stroke="black" d="M67.0234,-41.6019C61.0234,-41.6019 55.0234,-35.6019 55.0234,-29.6019"></path>
<polyline fill="none" stroke="black" points="55.0234,-29.6019 55.0234,-12.3981 "></polyline>
<path fill="none" stroke="black" d="M55.0234,-12.3981C55.0234,-6.3981 61.0234,-0.398095 67.0234,-0.398095"></path>
<polyline fill="none" stroke="black" points="67.0234,-0.398095 160.977,-0.398095 "></polyline>
<path fill="none" stroke="black" d="M160.977,-0.398095C166.977,-0.398095 172.977,-6.3981 172.977,-12.3981"></path>
<polyline fill="none" stroke="black" points="172.977,-12.3981 172.977,-29.6019 "></polyline>
<path fill="none" stroke="black" d="M172.977,-29.6019C172.977,-35.6019 166.977,-41.6019 160.977,-41.6019"></path>
<text text-anchor="middle" x="114" y="-25.2" font-family="Times,serif" font-size="14.00">UpdateExpression</text>
<text text-anchor="middle" x="114" y="-8.4" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
</g>
<g id="edge5" class="edge"><title>s1_3-&gt;s1_4</title>
<path fill="none" stroke="black" d="M88.0256,-77.8174C92.2417,-68.7572 96.5653,-59.4661 100.445,-51.1281"></path>
<polygon fill="black" stroke="black" points="103.718,-52.392 104.763,-41.8489 97.3711,-49.4386 103.718,-52.392"></polygon>
</g>
<g id="edge7" class="edge"><title>s1_4-&gt;s1_2</title>
<path fill="none" stroke="red" d="M127.225,-41.8137C133.324,-52.1325 139.891,-65.235 143,-78 152.676,-117.727 151.633,-130.033 143,-170 141.091,-178.837 137.857,-187.92 134.226,-196.368"></path>
<polygon fill="red" stroke="red" points="130.985,-195.038 130.005,-205.588 137.35,-197.952 130.985,-195.038"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -0,0 +1,149 @@
<?xml version="1.0"?>
<svg width="332pt" height="472pt" viewBox="0.00 0.00 332.00 472.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 468)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="162" cy="-455" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="214.617,-409.3 109.383,-409.3 97.3833,-397.3 97.3833,-312.7 109.383,-300.7 214.617,-300.7 226.617,-312.7 226.617,-397.3 214.617,-409.3"></polygon>
<path fill="white" stroke="white" d="M109.383,-409.3C103.383,-409.3 97.3833,-403.3 97.3833,-397.3"></path>
<path fill="white" stroke="white" d="M97.3833,-312.7C97.3833,-306.7 103.383,-300.7 109.383,-300.7"></path>
<path fill="white" stroke="white" d="M214.617,-300.7C220.617,-300.7 226.617,-306.7 226.617,-312.7"></path>
<path fill="white" stroke="white" d="M226.617,-397.3C226.617,-403.3 220.617,-409.3 214.617,-409.3"></path>
<polyline fill="none" stroke="black" points="214.617,-409.3 109.383,-409.3 "></polyline>
<path fill="none" stroke="black" d="M109.383,-409.3C103.383,-409.3 97.3833,-403.3 97.3833,-397.3"></path>
<polyline fill="none" stroke="black" points="97.3833,-397.3 97.3833,-312.7 "></polyline>
<path fill="none" stroke="black" d="M97.3833,-312.7C97.3833,-306.7 103.383,-300.7 109.383,-300.7"></path>
<polyline fill="none" stroke="black" points="109.383,-300.7 214.617,-300.7 "></polyline>
<path fill="none" stroke="black" d="M214.617,-300.7C220.617,-300.7 226.617,-306.7 226.617,-312.7"></path>
<polyline fill="none" stroke="black" points="226.617,-312.7 226.617,-397.3 "></polyline>
<path fill="none" stroke="black" d="M226.617,-397.3C226.617,-403.3 220.617,-409.3 214.617,-409.3"></path>
<text text-anchor="middle" x="162" y="-392.8" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="162" y="-376" font-family="Times,serif" font-size="14.00">ForStatement</text>
<text text-anchor="middle" x="162" y="-359.2" font-family="Times,serif" font-size="14.00">VariableDeclaration</text>
<text text-anchor="middle" x="162" y="-342.4" font-family="Times,serif" font-size="14.00">VariableDeclarator</text>
<text text-anchor="middle" x="162" y="-325.6" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="162" y="-308.8" font-family="Times,serif" font-size="14.00">Literal (0)</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M162,-445.98C162,-439.675 162,-430.238 162,-419.813"></path>
<polygon fill="black" stroke="black" points="165.5,-419.586 162,-409.586 158.5,-419.586 165.5,-419.586"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="257" cy="-21" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="257" cy="-21" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="208.233,-264.401 115.767,-264.401 103.767,-252.401 103.767,-217.599 115.767,-205.599 208.233,-205.599 220.233,-217.599 220.233,-252.401 208.233,-264.401"></polygon>
<path fill="white" stroke="white" d="M115.767,-264.401C109.767,-264.401 103.767,-258.401 103.767,-252.401"></path>
<path fill="white" stroke="white" d="M103.767,-217.599C103.767,-211.599 109.767,-205.599 115.767,-205.599"></path>
<path fill="white" stroke="white" d="M208.233,-205.599C214.233,-205.599 220.233,-211.599 220.233,-217.599"></path>
<path fill="white" stroke="white" d="M220.233,-252.401C220.233,-258.401 214.233,-264.401 208.233,-264.401"></path>
<polyline fill="none" stroke="black" points="208.233,-264.401 115.767,-264.401 "></polyline>
<path fill="none" stroke="black" d="M115.767,-264.401C109.767,-264.401 103.767,-258.401 103.767,-252.401"></path>
<polyline fill="none" stroke="black" points="103.767,-252.401 103.767,-217.599 "></polyline>
<path fill="none" stroke="black" d="M103.767,-217.599C103.767,-211.599 109.767,-205.599 115.767,-205.599"></path>
<polyline fill="none" stroke="black" points="115.767,-205.599 208.233,-205.599 "></polyline>
<path fill="none" stroke="black" d="M208.233,-205.599C214.233,-205.599 220.233,-211.599 220.233,-217.599"></path>
<polyline fill="none" stroke="black" points="220.233,-217.599 220.233,-252.401 "></polyline>
<path fill="none" stroke="black" d="M220.233,-252.401C220.233,-258.401 214.233,-264.401 208.233,-264.401"></path>
<text text-anchor="middle" x="162" y="-247.6" font-family="Times,serif" font-size="14.00">BinaryExpression</text>
<text text-anchor="middle" x="162" y="-230.8" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
<text text-anchor="middle" x="162" y="-214" font-family="Times,serif" font-size="14.00">Literal (10)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M162,-300.524C162,-291.777 162,-282.867 162,-274.572"></path>
<polygon fill="black" stroke="black" points="165.5,-274.452 162,-264.452 158.5,-274.452 165.5,-274.452"></polygon>
</g>
<g id="node5" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="122.147,-170 11.8526,-170 -0.147372,-158 -0.147372,-90 11.8526,-78 122.147,-78 134.147,-90 134.147,-158 122.147,-170"></polygon>
<path fill="white" stroke="white" d="M11.8526,-170C5.85263,-170 -0.147372,-164 -0.147372,-158"></path>
<path fill="white" stroke="white" d="M-0.147372,-90C-0.147372,-84 5.85263,-78 11.8526,-78"></path>
<path fill="white" stroke="white" d="M122.147,-78C128.147,-78 134.147,-84 134.147,-90"></path>
<path fill="white" stroke="white" d="M134.147,-158C134.147,-164 128.147,-170 122.147,-170"></path>
<polyline fill="none" stroke="black" points="122.147,-170 11.8526,-170 "></polyline>
<path fill="none" stroke="black" d="M11.8526,-170C5.85263,-170 -0.147372,-164 -0.147372,-158"></path>
<polyline fill="none" stroke="black" points="-0.147372,-158 -0.147372,-90 "></polyline>
<path fill="none" stroke="black" d="M-0.147372,-90C-0.147372,-84 5.85263,-78 11.8526,-78"></path>
<polyline fill="none" stroke="black" points="11.8526,-78 122.147,-78 "></polyline>
<path fill="none" stroke="black" d="M122.147,-78C128.147,-78 134.147,-84 134.147,-90"></path>
<polyline fill="none" stroke="black" points="134.147,-90 134.147,-158 "></polyline>
<path fill="none" stroke="black" d="M134.147,-158C134.147,-164 128.147,-170 122.147,-170"></path>
<text text-anchor="middle" x="67" y="-153.4" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="67" y="-136.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="67" y="-119.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="67" y="-103" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
<text text-anchor="middle" x="67" y="-86.2" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M137.288,-205.646C129.826,-197.085 121.382,-187.396 113,-177.779"></path>
<polygon fill="black" stroke="black" points="115.52,-175.343 106.311,-170.104 110.243,-179.942 115.52,-175.343"></polygon>
</g>
<g id="node7" class="node"><title>s1_5</title>
<polygon fill="white" stroke="white" points="312.147,-153.401 201.853,-153.401 189.853,-141.401 189.853,-106.599 201.853,-94.5986 312.147,-94.5986 324.147,-106.599 324.147,-141.401 312.147,-153.401"></polygon>
<path fill="white" stroke="white" d="M201.853,-153.401C195.853,-153.401 189.853,-147.401 189.853,-141.401"></path>
<path fill="white" stroke="white" d="M189.853,-106.599C189.853,-100.599 195.853,-94.5986 201.853,-94.5986"></path>
<path fill="white" stroke="white" d="M312.147,-94.5986C318.147,-94.5986 324.147,-100.599 324.147,-106.599"></path>
<path fill="white" stroke="white" d="M324.147,-141.401C324.147,-147.401 318.147,-153.401 312.147,-153.401"></path>
<polyline fill="none" stroke="black" points="312.147,-153.401 201.853,-153.401 "></polyline>
<path fill="none" stroke="black" d="M201.853,-153.401C195.853,-153.401 189.853,-147.401 189.853,-141.401"></path>
<polyline fill="none" stroke="black" points="189.853,-141.401 189.853,-106.599 "></polyline>
<path fill="none" stroke="black" d="M189.853,-106.599C189.853,-100.599 195.853,-94.5986 201.853,-94.5986"></path>
<polyline fill="none" stroke="black" points="201.853,-94.5986 312.147,-94.5986 "></polyline>
<path fill="none" stroke="black" d="M312.147,-94.5986C318.147,-94.5986 324.147,-100.599 324.147,-106.599"></path>
<polyline fill="none" stroke="black" points="324.147,-106.599 324.147,-141.401 "></polyline>
<path fill="none" stroke="black" d="M324.147,-141.401C324.147,-147.401 318.147,-153.401 312.147,-153.401"></path>
<text text-anchor="middle" x="257" y="-136.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="257" y="-119.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="257" y="-103" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge7" class="edge"><title>s1_2-&gt;s1_5</title>
<path fill="none" stroke="black" d="M186.712,-205.646C198.587,-192.021 212.952,-175.539 225.593,-161.035"></path>
<polygon fill="black" stroke="black" points="228.48,-163.05 232.412,-153.212 223.203,-158.451 228.48,-163.05"></polygon>
</g>
<g id="node6" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="160.977,-41.6019 67.0234,-41.6019 55.0234,-29.6019 55.0234,-12.3981 67.0234,-0.398095 160.977,-0.398095 172.977,-12.3981 172.977,-29.6019 160.977,-41.6019"></polygon>
<path fill="white" stroke="white" d="M67.0234,-41.6019C61.0234,-41.6019 55.0234,-35.6019 55.0234,-29.6019"></path>
<path fill="white" stroke="white" d="M55.0234,-12.3981C55.0234,-6.3981 61.0234,-0.398095 67.0234,-0.398095"></path>
<path fill="white" stroke="white" d="M160.977,-0.398095C166.977,-0.398095 172.977,-6.3981 172.977,-12.3981"></path>
<path fill="white" stroke="white" d="M172.977,-29.6019C172.977,-35.6019 166.977,-41.6019 160.977,-41.6019"></path>
<polyline fill="none" stroke="black" points="160.977,-41.6019 67.0234,-41.6019 "></polyline>
<path fill="none" stroke="black" d="M67.0234,-41.6019C61.0234,-41.6019 55.0234,-35.6019 55.0234,-29.6019"></path>
<polyline fill="none" stroke="black" points="55.0234,-29.6019 55.0234,-12.3981 "></polyline>
<path fill="none" stroke="black" d="M55.0234,-12.3981C55.0234,-6.3981 61.0234,-0.398095 67.0234,-0.398095"></path>
<polyline fill="none" stroke="black" points="67.0234,-0.398095 160.977,-0.398095 "></polyline>
<path fill="none" stroke="black" d="M160.977,-0.398095C166.977,-0.398095 172.977,-6.3981 172.977,-12.3981"></path>
<polyline fill="none" stroke="black" points="172.977,-12.3981 172.977,-29.6019 "></polyline>
<path fill="none" stroke="black" d="M172.977,-29.6019C172.977,-35.6019 166.977,-41.6019 160.977,-41.6019"></path>
<text text-anchor="middle" x="114" y="-25.2" font-family="Times,serif" font-size="14.00">UpdateExpression</text>
<text text-anchor="middle" x="114" y="-8.4" font-family="Times,serif" font-size="14.00">Identifier (i)</text>
</g>
<g id="edge5" class="edge"><title>s1_3-&gt;s1_4</title>
<path fill="none" stroke="black" d="M88.0256,-77.8174C92.2417,-68.7572 96.5653,-59.4661 100.445,-51.1281"></path>
<polygon fill="black" stroke="black" points="103.718,-52.392 104.763,-41.8489 97.3711,-49.4386 103.718,-52.392"></polygon>
</g>
<g id="edge6" class="edge"><title>s1_4-&gt;s1_2</title>
<path fill="none" stroke="black" d="M126.427,-41.7344C132.399,-52.1392 139.091,-65.3421 143,-78 155.006,-116.879 159.472,-163.404 161.108,-195.471"></path>
<polygon fill="black" stroke="black" points="157.624,-195.923 161.561,-205.76 164.618,-195.615 157.624,-195.923"></polygon>
</g>
<g id="edge8" class="edge"><title>s1_5-&gt;final</title>
<path fill="none" stroke="black" d="M257,-94.5971C257,-78.6959 257,-59.1538 257,-44.3521"></path>
<polygon fill="black" stroke="black" points="260.5,-44.0959 257,-34.0959 253.5,-44.096 260.5,-44.0959"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,82 @@
<?xml version="1.0"?>
<svg width="152pt" height="322pt" viewBox="0.00 0.00 152.00 322.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 318)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="72" cy="-305" rx="9" ry="9"></ellipse>
</g>
<g id="node2" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="113.149,-259.602 30.8505,-259.602 18.8505,-247.602 18.8505,-230.398 30.8505,-218.398 113.149,-218.398 125.149,-230.398 125.149,-247.602 113.149,-259.602"></polygon>
<path fill="white" stroke="white" d="M30.8505,-259.602C24.8505,-259.602 18.8505,-253.602 18.8505,-247.602"></path>
<path fill="white" stroke="white" d="M18.8505,-230.398C18.8505,-224.398 24.8505,-218.398 30.8505,-218.398"></path>
<path fill="white" stroke="white" d="M113.149,-218.398C119.149,-218.398 125.149,-224.398 125.149,-230.398"></path>
<path fill="white" stroke="white" d="M125.149,-247.602C125.149,-253.602 119.149,-259.602 113.149,-259.602"></path>
<polyline fill="none" stroke="black" points="113.149,-259.602 30.8505,-259.602 "></polyline>
<path fill="none" stroke="black" d="M30.8505,-259.602C24.8505,-259.602 18.8505,-253.602 18.8505,-247.602"></path>
<polyline fill="none" stroke="black" points="18.8505,-247.602 18.8505,-230.398 "></polyline>
<path fill="none" stroke="black" d="M18.8505,-230.398C18.8505,-224.398 24.8505,-218.398 30.8505,-218.398"></path>
<polyline fill="none" stroke="black" points="30.8505,-218.398 113.149,-218.398 "></polyline>
<path fill="none" stroke="black" d="M113.149,-218.398C119.149,-218.398 125.149,-224.398 125.149,-230.398"></path>
<polyline fill="none" stroke="black" points="125.149,-230.398 125.149,-247.602 "></polyline>
<path fill="none" stroke="black" d="M125.149,-247.602C125.149,-253.602 119.149,-259.602 113.149,-259.602"></path>
<text text-anchor="middle" x="72" y="-243.2" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="72" y="-226.4" font-family="Times,serif" font-size="14.00">WhileStatement</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M72,-295.894C72,-289.274 72,-279.485 72,-269.94"></path>
<polygon fill="black" stroke="black" points="75.5001,-269.842 72,-259.842 68.5001,-269.842 75.5001,-269.842"></polygon>
</g>
<g id="node3" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="103.339,-182 40.6614,-182 28.6614,-170 28.6614,-158 40.6614,-146 103.339,-146 115.339,-158 115.339,-170 103.339,-182"></polygon>
<path fill="white" stroke="white" d="M40.6614,-182C34.6614,-182 28.6614,-176 28.6614,-170"></path>
<path fill="white" stroke="white" d="M28.6614,-158C28.6614,-152 34.6614,-146 40.6614,-146"></path>
<path fill="white" stroke="white" d="M103.339,-146C109.339,-146 115.339,-152 115.339,-158"></path>
<path fill="white" stroke="white" d="M115.339,-170C115.339,-176 109.339,-182 103.339,-182"></path>
<polyline fill="none" stroke="black" points="103.339,-182 40.6614,-182 "></polyline>
<path fill="none" stroke="black" d="M40.6614,-182C34.6614,-182 28.6614,-176 28.6614,-170"></path>
<polyline fill="none" stroke="black" points="28.6614,-170 28.6614,-158 "></polyline>
<path fill="none" stroke="black" d="M28.6614,-158C28.6614,-152 34.6614,-146 40.6614,-146"></path>
<polyline fill="none" stroke="black" points="40.6614,-146 103.339,-146 "></polyline>
<path fill="none" stroke="black" d="M103.339,-146C109.339,-146 115.339,-152 115.339,-158"></path>
<polyline fill="none" stroke="black" points="115.339,-158 115.339,-170 "></polyline>
<path fill="none" stroke="black" d="M115.339,-170C115.339,-176 109.339,-182 103.339,-182"></path>
<text text-anchor="middle" x="72" y="-159.8" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M72,-218.052C72,-210.216 72,-201.089 72,-192.636"></path>
<polygon fill="black" stroke="black" points="75.5001,-192.439 72,-182.439 68.5001,-192.439 75.5001,-192.439"></polygon>
</g>
<g id="node4" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="132.317,-109.3 11.6828,-109.3 -0.317209,-97.3002 -0.317209,-12.6998 11.6828,-0.699817 132.317,-0.699817 144.317,-12.6998 144.317,-97.3002 132.317,-109.3"></polygon>
<path fill="white" stroke="white" d="M11.6828,-109.3C5.68279,-109.3 -0.317209,-103.3 -0.317209,-97.3002"></path>
<path fill="white" stroke="white" d="M-0.317209,-12.6998C-0.317209,-6.69982 5.68279,-0.699817 11.6828,-0.699817"></path>
<path fill="white" stroke="white" d="M132.317,-0.699817C138.317,-0.699817 144.317,-6.69982 144.317,-12.6998"></path>
<path fill="white" stroke="white" d="M144.317,-97.3002C144.317,-103.3 138.317,-109.3 132.317,-109.3"></path>
<polyline fill="none" stroke="black" points="132.317,-109.3 11.6828,-109.3 "></polyline>
<path fill="none" stroke="black" d="M11.6828,-109.3C5.68279,-109.3 -0.317209,-103.3 -0.317209,-97.3002"></path>
<polyline fill="none" stroke="black" points="-0.317209,-97.3002 -0.317209,-12.6998 "></polyline>
<path fill="none" stroke="black" d="M-0.317209,-12.6998C-0.317209,-6.69982 5.68279,-0.699817 11.6828,-0.699817"></path>
<polyline fill="none" stroke="black" points="11.6828,-0.699817 132.317,-0.699817 "></polyline>
<path fill="none" stroke="black" d="M132.317,-0.699817C138.317,-0.699817 144.317,-6.69982 144.317,-12.6998"></path>
<polyline fill="none" stroke="black" points="144.317,-12.6998 144.317,-97.3002 "></polyline>
<path fill="none" stroke="black" d="M144.317,-97.3002C144.317,-103.3 138.317,-109.3 132.317,-109.3"></path>
<text text-anchor="middle" x="72" y="-92.8" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="72" y="-76" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="72" y="-59.2" font-family="Times,serif" font-size="14.00">AssignmentExpression</text>
<text text-anchor="middle" x="72" y="-42.4" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
<text text-anchor="middle" x="72" y="-25.6" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="72" y="-8.8" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M72,-145.809C72,-138.443 72,-129.338 72,-119.779"></path>
<polygon fill="black" stroke="black" points="75.5001,-119.706 72,-109.706 68.5001,-119.706 75.5001,-119.706"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,87 @@
<?xml version="1.0"?>
<svg width="152pt" height="322pt" viewBox="0.00 0.00 152.00 322.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 318)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="72" cy="-305" rx="9" ry="9"></ellipse>
</g>
<g id="node2" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="113.149,-259.602 30.8505,-259.602 18.8505,-247.602 18.8505,-230.398 30.8505,-218.398 113.149,-218.398 125.149,-230.398 125.149,-247.602 113.149,-259.602"></polygon>
<path fill="white" stroke="white" d="M30.8505,-259.602C24.8505,-259.602 18.8505,-253.602 18.8505,-247.602"></path>
<path fill="white" stroke="white" d="M18.8505,-230.398C18.8505,-224.398 24.8505,-218.398 30.8505,-218.398"></path>
<path fill="white" stroke="white" d="M113.149,-218.398C119.149,-218.398 125.149,-224.398 125.149,-230.398"></path>
<path fill="white" stroke="white" d="M125.149,-247.602C125.149,-253.602 119.149,-259.602 113.149,-259.602"></path>
<polyline fill="none" stroke="black" points="113.149,-259.602 30.8505,-259.602 "></polyline>
<path fill="none" stroke="black" d="M30.8505,-259.602C24.8505,-259.602 18.8505,-253.602 18.8505,-247.602"></path>
<polyline fill="none" stroke="black" points="18.8505,-247.602 18.8505,-230.398 "></polyline>
<path fill="none" stroke="black" d="M18.8505,-230.398C18.8505,-224.398 24.8505,-218.398 30.8505,-218.398"></path>
<polyline fill="none" stroke="black" points="30.8505,-218.398 113.149,-218.398 "></polyline>
<path fill="none" stroke="black" d="M113.149,-218.398C119.149,-218.398 125.149,-224.398 125.149,-230.398"></path>
<polyline fill="none" stroke="black" points="125.149,-230.398 125.149,-247.602 "></polyline>
<path fill="none" stroke="black" d="M125.149,-247.602C125.149,-253.602 119.149,-259.602 113.149,-259.602"></path>
<text text-anchor="middle" x="72" y="-243.2" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="72" y="-226.4" font-family="Times,serif" font-size="14.00">WhileStatement</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M72,-295.894C72,-289.274 72,-279.485 72,-269.94"></path>
<polygon fill="black" stroke="black" points="75.5001,-269.842 72,-259.842 68.5001,-269.842 75.5001,-269.842"></polygon>
</g>
<g id="node3" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="103.339,-182 40.6614,-182 28.6614,-170 28.6614,-158 40.6614,-146 103.339,-146 115.339,-158 115.339,-170 103.339,-182"></polygon>
<path fill="white" stroke="white" d="M40.6614,-182C34.6614,-182 28.6614,-176 28.6614,-170"></path>
<path fill="white" stroke="white" d="M28.6614,-158C28.6614,-152 34.6614,-146 40.6614,-146"></path>
<path fill="white" stroke="white" d="M103.339,-146C109.339,-146 115.339,-152 115.339,-158"></path>
<path fill="white" stroke="white" d="M115.339,-170C115.339,-176 109.339,-182 103.339,-182"></path>
<polyline fill="none" stroke="black" points="103.339,-182 40.6614,-182 "></polyline>
<path fill="none" stroke="black" d="M40.6614,-182C34.6614,-182 28.6614,-176 28.6614,-170"></path>
<polyline fill="none" stroke="black" points="28.6614,-170 28.6614,-158 "></polyline>
<path fill="none" stroke="black" d="M28.6614,-158C28.6614,-152 34.6614,-146 40.6614,-146"></path>
<polyline fill="none" stroke="black" points="40.6614,-146 103.339,-146 "></polyline>
<path fill="none" stroke="black" d="M103.339,-146C109.339,-146 115.339,-152 115.339,-158"></path>
<polyline fill="none" stroke="black" points="115.339,-158 115.339,-170 "></polyline>
<path fill="none" stroke="black" d="M115.339,-170C115.339,-176 109.339,-182 103.339,-182"></path>
<text text-anchor="middle" x="72" y="-159.8" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M72,-218.052C72,-210.216 72,-201.089 72,-192.636"></path>
<polygon fill="black" stroke="black" points="75.5001,-192.439 72,-182.439 68.5001,-192.439 75.5001,-192.439"></polygon>
</g>
<g id="node4" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="132.317,-109.3 11.6828,-109.3 -0.317209,-97.3002 -0.317209,-12.6998 11.6828,-0.699817 132.317,-0.699817 144.317,-12.6998 144.317,-97.3002 132.317,-109.3"></polygon>
<path fill="white" stroke="white" d="M11.6828,-109.3C5.68279,-109.3 -0.317209,-103.3 -0.317209,-97.3002"></path>
<path fill="white" stroke="white" d="M-0.317209,-12.6998C-0.317209,-6.69982 5.68279,-0.699817 11.6828,-0.699817"></path>
<path fill="white" stroke="white" d="M132.317,-0.699817C138.317,-0.699817 144.317,-6.69982 144.317,-12.6998"></path>
<path fill="white" stroke="white" d="M144.317,-97.3002C144.317,-103.3 138.317,-109.3 132.317,-109.3"></path>
<polyline fill="none" stroke="black" points="132.317,-109.3 11.6828,-109.3 "></polyline>
<path fill="none" stroke="black" d="M11.6828,-109.3C5.68279,-109.3 -0.317209,-103.3 -0.317209,-97.3002"></path>
<polyline fill="none" stroke="black" points="-0.317209,-97.3002 -0.317209,-12.6998 "></polyline>
<path fill="none" stroke="black" d="M-0.317209,-12.6998C-0.317209,-6.69982 5.68279,-0.699817 11.6828,-0.699817"></path>
<polyline fill="none" stroke="black" points="11.6828,-0.699817 132.317,-0.699817 "></polyline>
<path fill="none" stroke="black" d="M132.317,-0.699817C138.317,-0.699817 144.317,-6.69982 144.317,-12.6998"></path>
<polyline fill="none" stroke="black" points="144.317,-12.6998 144.317,-97.3002 "></polyline>
<path fill="none" stroke="black" d="M144.317,-97.3002C144.317,-103.3 138.317,-109.3 132.317,-109.3"></path>
<text text-anchor="middle" x="72" y="-92.8" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="72" y="-76" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="72" y="-59.2" font-family="Times,serif" font-size="14.00">AssignmentExpression</text>
<text text-anchor="middle" x="72" y="-42.4" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
<text text-anchor="middle" x="72" y="-25.6" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="72" y="-8.8" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M66.8852,-145.809C66.0803,-138.443 65.5726,-129.338 65.362,-119.779"></path>
<polygon fill="black" stroke="black" points="68.861,-119.666 65.25,-109.706 61.8615,-119.744 68.861,-119.666"></polygon>
</g>
<g id="edge6" class="edge"><title>s1_3-&gt;s1_2</title>
<path fill="none" stroke="red" d="M78.75,-109.706C78.7461,-118.71 78.4872,-127.707 77.9735,-135.675"></path>
<polygon fill="red" stroke="red" points="74.4717,-135.549 77.1148,-145.809 81.4467,-136.14 74.4717,-135.549"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -0,0 +1,121 @@
<?xml version="1.0"?>
<svg width="305pt" height="384pt" viewBox="0.00 0.00 305.00 384.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 380)">
<title>_anonymous_0</title>
<g id="node1" class="node"><title>initial</title>
<ellipse fill="black" stroke="black" cx="72" cy="-367" rx="9" ry="9"></ellipse>
</g>
<g id="node3" class="node"><title>s1_1</title>
<polygon fill="white" stroke="white" points="113.149,-321.602 30.8505,-321.602 18.8505,-309.602 18.8505,-292.398 30.8505,-280.398 113.149,-280.398 125.149,-292.398 125.149,-309.602 113.149,-321.602"></polygon>
<path fill="white" stroke="white" d="M30.8505,-321.602C24.8505,-321.602 18.8505,-315.602 18.8505,-309.602"></path>
<path fill="white" stroke="white" d="M18.8505,-292.398C18.8505,-286.398 24.8505,-280.398 30.8505,-280.398"></path>
<path fill="white" stroke="white" d="M113.149,-280.398C119.149,-280.398 125.149,-286.398 125.149,-292.398"></path>
<path fill="white" stroke="white" d="M125.149,-309.602C125.149,-315.602 119.149,-321.602 113.149,-321.602"></path>
<polyline fill="none" stroke="black" points="113.149,-321.602 30.8505,-321.602 "></polyline>
<path fill="none" stroke="black" d="M30.8505,-321.602C24.8505,-321.602 18.8505,-315.602 18.8505,-309.602"></path>
<polyline fill="none" stroke="black" points="18.8505,-309.602 18.8505,-292.398 "></polyline>
<path fill="none" stroke="black" d="M18.8505,-292.398C18.8505,-286.398 24.8505,-280.398 30.8505,-280.398"></path>
<polyline fill="none" stroke="black" points="30.8505,-280.398 113.149,-280.398 "></polyline>
<path fill="none" stroke="black" d="M113.149,-280.398C119.149,-280.398 125.149,-286.398 125.149,-292.398"></path>
<polyline fill="none" stroke="black" points="125.149,-292.398 125.149,-309.602 "></polyline>
<path fill="none" stroke="black" d="M125.149,-309.602C125.149,-315.602 119.149,-321.602 113.149,-321.602"></path>
<text text-anchor="middle" x="72" y="-305.2" font-family="Times,serif" font-size="14.00">Program</text>
<text text-anchor="middle" x="72" y="-288.4" font-family="Times,serif" font-size="14.00">WhileStatement</text>
</g>
<g id="edge2" class="edge"><title>initial-&gt;s1_1</title>
<path fill="none" stroke="black" d="M72,-357.894C72,-351.274 72,-341.485 72,-331.94"></path>
<polygon fill="black" stroke="black" points="75.5001,-331.842 72,-321.842 68.5001,-331.842 75.5001,-331.842"></polygon>
</g>
<g id="node2" class="node"><title>final</title>
<ellipse fill="black" stroke="black" cx="230" cy="-13" rx="9" ry="9"></ellipse>
<ellipse fill="none" stroke="black" cx="230" cy="-13" rx="13" ry="13"></ellipse>
</g>
<g id="node4" class="node"><title>s1_2</title>
<polygon fill="white" stroke="white" points="103.339,-244 40.6614,-244 28.6614,-232 28.6614,-220 40.6614,-208 103.339,-208 115.339,-220 115.339,-232 103.339,-244"></polygon>
<path fill="white" stroke="white" d="M40.6614,-244C34.6614,-244 28.6614,-238 28.6614,-232"></path>
<path fill="white" stroke="white" d="M28.6614,-220C28.6614,-214 34.6614,-208 40.6614,-208"></path>
<path fill="white" stroke="white" d="M103.339,-208C109.339,-208 115.339,-214 115.339,-220"></path>
<path fill="white" stroke="white" d="M115.339,-232C115.339,-238 109.339,-244 103.339,-244"></path>
<polyline fill="none" stroke="black" points="103.339,-244 40.6614,-244 "></polyline>
<path fill="none" stroke="black" d="M40.6614,-244C34.6614,-244 28.6614,-238 28.6614,-232"></path>
<polyline fill="none" stroke="black" points="28.6614,-232 28.6614,-220 "></polyline>
<path fill="none" stroke="black" d="M28.6614,-220C28.6614,-214 34.6614,-208 40.6614,-208"></path>
<polyline fill="none" stroke="black" points="40.6614,-208 103.339,-208 "></polyline>
<path fill="none" stroke="black" d="M103.339,-208C109.339,-208 115.339,-214 115.339,-220"></path>
<polyline fill="none" stroke="black" points="115.339,-220 115.339,-232 "></polyline>
<path fill="none" stroke="black" d="M115.339,-232C115.339,-238 109.339,-244 103.339,-244"></path>
<text text-anchor="middle" x="72" y="-221.8" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
</g>
<g id="edge3" class="edge"><title>s1_1-&gt;s1_2</title>
<path fill="none" stroke="black" d="M72,-280.052C72,-272.216 72,-263.089 72,-254.636"></path>
<polygon fill="black" stroke="black" points="75.5001,-254.439 72,-244.439 68.5001,-254.439 75.5001,-254.439"></polygon>
</g>
<g id="node5" class="node"><title>s1_3</title>
<polygon fill="white" stroke="white" points="132.317,-171.3 11.6828,-171.3 -0.317209,-159.3 -0.317209,-74.6998 11.6828,-62.6998 132.317,-62.6998 144.317,-74.6998 144.317,-159.3 132.317,-171.3"></polygon>
<path fill="white" stroke="white" d="M11.6828,-171.3C5.68279,-171.3 -0.317209,-165.3 -0.317209,-159.3"></path>
<path fill="white" stroke="white" d="M-0.317209,-74.6998C-0.317209,-68.6998 5.68279,-62.6998 11.6828,-62.6998"></path>
<path fill="white" stroke="white" d="M132.317,-62.6998C138.317,-62.6998 144.317,-68.6998 144.317,-74.6998"></path>
<path fill="white" stroke="white" d="M144.317,-159.3C144.317,-165.3 138.317,-171.3 132.317,-171.3"></path>
<polyline fill="none" stroke="black" points="132.317,-171.3 11.6828,-171.3 "></polyline>
<path fill="none" stroke="black" d="M11.6828,-171.3C5.68279,-171.3 -0.317209,-165.3 -0.317209,-159.3"></path>
<polyline fill="none" stroke="black" points="-0.317209,-159.3 -0.317209,-74.6998 "></polyline>
<path fill="none" stroke="black" d="M-0.317209,-74.6998C-0.317209,-68.6998 5.68279,-62.6998 11.6828,-62.6998"></path>
<polyline fill="none" stroke="black" points="11.6828,-62.6998 132.317,-62.6998 "></polyline>
<path fill="none" stroke="black" d="M132.317,-62.6998C138.317,-62.6998 144.317,-68.6998 144.317,-74.6998"></path>
<polyline fill="none" stroke="black" points="144.317,-74.6998 144.317,-159.3 "></polyline>
<path fill="none" stroke="black" d="M144.317,-159.3C144.317,-165.3 138.317,-171.3 132.317,-171.3"></path>
<text text-anchor="middle" x="72" y="-154.8" font-family="Times,serif" font-size="14.00">BlockStatement</text>
<text text-anchor="middle" x="72" y="-138" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="72" y="-121.2" font-family="Times,serif" font-size="14.00">AssignmentExpression</text>
<text text-anchor="middle" x="72" y="-104.4" font-family="Times,serif" font-size="14.00">Identifier (a)</text>
<text text-anchor="middle" x="72" y="-87.6" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="72" y="-70.8" font-family="Times,serif" font-size="14.00">Identifier (foo)</text>
</g>
<g id="edge4" class="edge"><title>s1_2-&gt;s1_3</title>
<path fill="none" stroke="black" d="M66.8852,-207.809C66.0803,-200.443 65.5726,-191.338 65.362,-181.779"></path>
<polygon fill="black" stroke="black" points="68.861,-181.666 65.25,-171.706 61.8615,-181.744 68.861,-181.666"></polygon>
</g>
<g id="node6" class="node"><title>s1_4</title>
<polygon fill="white" stroke="white" points="285.147,-146.401 174.853,-146.401 162.853,-134.401 162.853,-99.5986 174.853,-87.5986 285.147,-87.5986 297.147,-99.5986 297.147,-134.401 285.147,-146.401"></polygon>
<path fill="white" stroke="white" d="M174.853,-146.401C168.853,-146.401 162.853,-140.401 162.853,-134.401"></path>
<path fill="white" stroke="white" d="M162.853,-99.5986C162.853,-93.5986 168.853,-87.5986 174.853,-87.5986"></path>
<path fill="white" stroke="white" d="M285.147,-87.5986C291.147,-87.5986 297.147,-93.5986 297.147,-99.5986"></path>
<path fill="white" stroke="white" d="M297.147,-134.401C297.147,-140.401 291.147,-146.401 285.147,-146.401"></path>
<polyline fill="none" stroke="black" points="285.147,-146.401 174.853,-146.401 "></polyline>
<path fill="none" stroke="black" d="M174.853,-146.401C168.853,-146.401 162.853,-140.401 162.853,-134.401"></path>
<polyline fill="none" stroke="black" points="162.853,-134.401 162.853,-99.5986 "></polyline>
<path fill="none" stroke="black" d="M162.853,-99.5986C162.853,-93.5986 168.853,-87.5986 174.853,-87.5986"></path>
<polyline fill="none" stroke="black" points="174.853,-87.5986 285.147,-87.5986 "></polyline>
<path fill="none" stroke="black" d="M285.147,-87.5986C291.147,-87.5986 297.147,-93.5986 297.147,-99.5986"></path>
<polyline fill="none" stroke="black" points="297.147,-99.5986 297.147,-134.401 "></polyline>
<path fill="none" stroke="black" d="M297.147,-134.401C297.147,-140.401 291.147,-146.401 285.147,-146.401"></path>
<text text-anchor="middle" x="230" y="-129.6" font-family="Times,serif" font-size="14.00">ExpressionStatement</text>
<text text-anchor="middle" x="230" y="-112.8" font-family="Times,serif" font-size="14.00">CallExpression</text>
<text text-anchor="middle" x="230" y="-96" font-family="Times,serif" font-size="14.00">Identifier (bar)</text>
</g>
<g id="edge6" class="edge"><title>s1_2-&gt;s1_4</title>
<path fill="none" stroke="black" d="M98.7745,-207.789C114.625,-197.523 135.053,-184.16 153,-172 162.409,-165.625 172.395,-158.724 181.947,-152.055"></path>
<polygon fill="black" stroke="black" points="184.021,-154.875 190.205,-146.273 180.006,-149.141 184.021,-154.875"></polygon>
</g>
<g id="edge5" class="edge"><title>s1_3-&gt;s1_2</title>
<path fill="none" stroke="black" d="M78.75,-171.706C78.7461,-180.71 78.4872,-189.707 77.9735,-197.675"></path>
<polygon fill="black" stroke="black" points="74.4717,-197.549 77.1148,-207.809 81.4467,-198.14 74.4717,-197.549"></polygon>
</g>
<g id="edge7" class="edge"><title>s1_4-&gt;final</title>
<path fill="none" stroke="black" d="M230,-87.5873C230,-71.4284 230,-51.4784 230,-36.4288"></path>
<polygon fill="black" stroke="black" points="233.5,-36.0194 230,-26.0195 226.5,-36.0195 233.5,-36.0194"></polygon>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -0,0 +1,41 @@
# Contributing
One of the great things about open source projects is that anyone can contribute in any number of meaningful ways. ESLint couldn't exist without the help of the many contributors it's had since the project began, and we want you to feel like you can contribute and make a difference as well.
This guide is intended for anyone who wants to contribute to an ESLint project. Please read it carefully as it answers a lot of the questions many newcomers have when first working with our projects.
## Read the [Code of Conduct](https://js.foundation/community/code-of-conduct)
ESLint welcomes contributions from everyone and adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct). We kindly request that you read over our code of conduct before contributing.
## [Signing the CLA](https://js.foundation/CLA)
In order to submit code or documentation to an ESLint project, you will need to electronically sign our [Contributor License Agreement](https://cla.js.foundation/eslint/eslint). The CLA is you giving us permission to use your contribution.
## [Bug Reporting](reporting-bugs)
Think you found a problem? We'd love to hear about it. This section explains how to submit a bug, the type of information we need to properly verify it, and the overall process.
## Proposing a [New Rule](new-rules.md)
We get a lot of proposals for new rules in ESLint. This section explains how we determine which rules are accepted and what information you should provide to help us evaluate your proposal.
## Proposing a [Rule Change](rule-changes.md)
Want to make a change to an existing rule? This section explains the process and how we evaluate such proposals.
## Requesting a [Change](changes.md)
If you'd like to request a change other than a bug fix or new rule, this section explains that process.
## Reporting a security vulnerability
To report a security vulnerability in ESLint, please use our [HackerOne program](https://hackerone.com/eslint).
## [Working on Issues](working-on-issues.md)
Have some extra time and want to contribute? This section talks about the process of working on issues.
## Submitting a [Pull Request](pull-requests.md)
We're always looking for contributions from the community. This section explains the requirements for pull requests and the process of contributing code.

View File

@ -0,0 +1,17 @@
# Change Requests
If you'd like to request a change to ESLint, please [create a new issue](https://github.com/eslint/eslint/issues/new?template=CHANGE.md) on GitHub. Be sure to include the following information:
1. The version of ESLint you are using.
1. The problem you want to solve.
1. Your take on the correct solution to problem.
If you're requesting a change to a rule, it's helpful to include this information as well:
1. What you did.
1. What you would like to happen.
1. What actually happened.
Please include as much detail as possible to help us properly address your issue. If we need to triage issues and constantly ask people for more detail, that's time taken away from actually fixing issues. Help us be as efficient as possible by including a lot of detail in your issues.
**Note:** If you just have a question that won't necessarily result in a change to ESLint, such as asking how something works or how to contribute, please use the [mailing list](https://groups.google.com/group/eslint) or [chat](https://gitter.im/eslint/eslint) instead of filing an issue.

View File

@ -0,0 +1,42 @@
# New Rules
ESLint is all about rules. For most of the project's lifetime, we've had over 200 rules, and that list continues to grow. However, we can't just accept any proposed rule because all rules need to work cohesively together. As such, we have some guidelines around which rules can be part of the ESLint core and which are better off as custom rules and plugins.
**Note:** As of 2016, we accept only rules that are deemed extremely important for inclusion. We prefer that new rules be implemented in plugins.
## Core Rule Guidelines
In general, ESLint core rules must be:
1. **Widely applicable.** The rules we distribute need to be of importance to a large number of developers. Individual preferences for uncommon patterns are not supported.
1. **Generic.** Rules cannot be so specific that users will have trouble understanding when to use them. A rule is typically too specific if describing what it does requires more than two "and"s (if a and b and c and d, then this rule warns).
1. **Atomic.** Rules must function completely on their own. Rules are expressly forbidden from knowing about the state or presence of other rules.
1. **Unique.** No two rules can produce the same warning. Overlapping rules confuse end users and there is an expectation that core ESLint rules do not overlap.
1. **Library agnostic.** Rules must be based solely on JavaScript runtime environments and not on specific libraries or frameworks. For example, core rules shouldn't only apply if you're using jQuery but we may have some rules that apply only if you're using Node.js (a runtime).
1. **No conflicts.** No rule must directly conflict with another rule. For example, if we have a rule requiring semicolons, we cannot also have a rule disallowing semicolons (which is why we have one rule, `semi`, that does both).
Even though these are the formal criteria for inclusion, each rule is evaluated on its own basis.
## Proposing a Rule
If you want to propose a new rule, please see how to [create a pull request](/docs/developer-guide/contributing/pull-requests) or submit an issue by filling out a [new rule template](https://github.com/eslint/eslint/issues/new?template=NEW_RULE.md).
We need all of this information in order to determine whether or not the rule is a good core rule candidate.
## Accepting a Rule
In order for a rule to be accepted in the ESLint core, it must:
1. Fulfill all the criteria listed in the "Core Rule Guidelines" section
1. Have an ESLint team member champion inclusion of the rule
1. Be very important for ESLint users because it either catches a serious problem or allows styling of code in accordance with a popular style guide
Keep in mind that we have over 200 rules, and that is daunting both for end users and the ESLint team (who has to maintain them). As such, any new rules must be deemed of high importance to be considered for inclusion in ESLint.
## Implementation is Your Responsibility
The ESLint team doesn't implement new rules that are suggested by users because we have a limited number of people and need to focus on the overall roadmap. Once a rule is accepted, you are responsible for implementing and documenting the rule. You may, alternately, recruit another person to help you implement the rule. The ESLint team member who championed the rule is your resource to help guide you through the rest of this process.
## Alternative: Creating Your Own Rules
Remember that ESLint is completely pluggable, which means you can create your own rules and distribute them using plugins. We did this on purpose because we don't want to be the gatekeepers for all possible rules. Even if we don't accept a rule into the core, that doesn't mean you can't have the exact rule that you want. See the [working with rules](../working-with-rules.md) and [working with plugins](../working-with-plugins.md) documentation for more information.

View File

@ -0,0 +1,182 @@
# Pull Requests
If you want to contribute to an ESLint repo, please use a GitHub pull request. This is the fastest way for us to evaluate your code and to merge it into the code base. Please don't file an issue with snippets of code. Doing so means that we need to manually merge the changes in and update any appropriate tests. That decreases the likelihood that your code is going to get included in a timely manner. Please use pull requests.
## Getting Started
If you'd like to work on a pull request and you've never submitted code before, follow these steps:
1. Sign our [Contributor License Agreement](https://cla.js.foundation/eslint/eslint).
1. Set up a [development environment](../development-environment.md).
1. If you want to implement a breaking change or a change to the core, ensure there's an issue that describes what you're doing and the issue has been accepted. You can create a new issue or just indicate you're [working on an existing issue](working-on-issues.md). Bug fixes, documentation changes, and other pull requests do not require an issue.
After that, you're ready to start working on code.
## Working with Code
The process of submitting a pull request is fairly straightforward and generally follows the same pattern each time:
1. [Create a new branch](#step1)
2. [Make your changes](#step2)
3. [Rebase onto upstream](#step3)
4. [Run the tests](#step4)
5. [Double check your submission](#step5)
6. [Push your changes](#step6)
7. [Submit the pull request](#step7)
Details about each step are found below.
### Step 1: Create a new branch<a name="step1"></a>
The first step to sending a pull request is to create a new branch in your ESLint fork. Give the branch a descriptive name that describes what it is you're fixing, such as:
```
$ git checkout -b issue1234
```
You should do all of your development for the issue in this branch.
**Note:** Do not combine fixes for multiple issues into one branch. Use a separate branch for each issue you're working on.
### Step 2: Make your changes<a name="step2"></a>
Make the changes to the code and tests, following the [code conventions](../code-conventions.md) as you go. Once you have finished, commit the changes to your branch:
```
$ git add -A
$ git commit
```
Our commit message format is as follows:
```
Tag: Short description (fixes #1234)
Longer description here if necessary
```
The first line of the commit message (the summary) must have a specific format. This format is checked by our build tools.
The `Tag` is one of the following:
* `Fix` - for a bug fix.
* `Update` - either for a backwards-compatible enhancement or for a rule change that adds reported problems.
* `New` - implemented a new feature.
* `Breaking` - for a backwards-incompatible enhancement or feature.
* `Docs` - changes to documentation only.
* `Build` - changes to build process only.
* `Upgrade` - for a dependency upgrade.
* `Chore` - for refactoring, adding tests, etc. (anything that isn't user-facing).
Use the [labels of the issue you are working on](working-on-issues.md#issue-labels) to determine the best tag.
The message summary should be a one-sentence description of the change, and it must be 72 characters in length or shorter. If the pull request addresses an issue, then the issue number should be mentioned at the end. If the commit doesn't completely fix the issue, then use `(refs #1234)` instead of `(fixes #1234)`.
Here are some good commit message summary examples:
```
Build: Update Travis to only test Node 0.10 (refs #734)
Fix: Semi rule incorrectly flagging extra semicolon (fixes #840)
Upgrade: Esprima to 1.2, switch to using comment attachment (fixes #730)
```
The commit message format is important because these messages are used to create a changelog for each release. The tag and issue number help to create more consistent and useful changelogs.
### Step 3: Rebase onto upstream<a name="step3"></a>
Before you send the pull request, be sure to rebase onto the upstream source. This ensures your code is running on the latest available code.
```
git fetch upstream
git rebase upstream/master
```
### Step 4: Run the tests<a name="step4"></a>
After rebasing, be sure to run all of the tests once again to make sure nothing broke:
```
npm test
```
If there are any failing tests, update your code until all tests pass.
### Step 5: Double check your submission<a name="step5"></a>
With your code ready to go, this is a good time to double-check your submission to make sure it follows our conventions. Here are the things to check:
* Make sure your commit is formatted correctly.
* The pull request must have a description. The description should explain what you did and how its effects can be seen.
* The commit message is properly formatted.
* The change introduces no functional regression. Be sure to run `npm test` to verify your changes before submitting a pull request.
* Make separate pull requests for unrelated changes. Large pull requests with multiple unrelated changes may be closed without merging.
* All changes must be accompanied by tests, even if the feature you're working on previously had no tests.
* All user-facing changes must be accompanied by appropriate documentation.
* Follow the [Code Conventions](../code-conventions.md).
### Step 6: Push your changes<a name="step6"></a>
Next, push your changes to your clone:
```
git push origin issue1234
```
If you are unable to push because some references are old, do a forced push instead:
```
git push -f origin issue1234
```
### Step 7: Send the pull request<a name="step7"></a>
Now you're ready to send the pull request. Go to your ESLint fork and then follow the [GitHub documentation](https://help.github.com/articles/creating-a-pull-request) on how to send a pull request.
## Following Up
Once your pull request is sent, it's time for the team to review it. As such, please make sure to:
1. Monitor the status of the Travis CI build for your pull request. If it fails, please investigate why. We cannot merge pull requests that fail Travis for any reason.
1. Respond to comments left on the pull request from team members. Remember, we want to help you land your code, so please be receptive to our feedback.
1. We may ask you to make changes, rebase, or squash your commits.
### Updating the Commit Message
If your commit message is in the incorrect format, you'll be asked to update it. You can do so via:
```
$ git commit --amend
```
This will open up your editor so you can make changes. After that, you'll need to do a forced push to your branch:
```
$ git push origin issue1234 -f
```
### Updating the Code
If we ask you to make code changes, there's no need to close the pull request and create a new one. Just go back to the branch on your fork and make your changes. Then, when you're ready, you can add your changes into the branch:
```
$ git add -A
$ git commit
$ git push origin issue1234
```
When updating the code, it's usually better to add additional commits to your branch rather than amending the original commit, because reviewers can easily tell which changes were made in response to a particular review. When we merge pull requests, we will squash all the commits from your branch into a single commit on the `master` branch.
### Rebasing
If your code is out-of-date, we might ask you to rebase. That means we want you to apply your changes on top of the latest upstream code. Make sure you have set up a [development environment](../development-environment.md) and then you can rebase using these commands:
```
$ git fetch upstream
$ git rebase upstream/master
```
You might find that there are merge conflicts when you attempt to rebase. Please [resolve the conflicts](https://help.github.com/articles/resolving-merge-conflicts-after-a-git-rebase/) and then do a forced push to your branch:
```
$ git push origin issue1234 -f
```

View File

@ -0,0 +1,7 @@
# Reporting Bugs
If you think you've found a bug in ESLint, please [create a new issue](https://github.com/eslint/eslint/issues/new) or a [pull request](/docs/developer-guide/contributing/pull-requests.md) on GitHub.
Please include as much detail as possible to help us properly address your issue. If we need to triage issues and constantly ask people for more detail, that's time taken away from actually fixing issues. Help us be as efficient as possible by including a lot of detail in your issues.
**Note:** If you just have a question that won't necessarily result in a change to ESLint, such as asking how something works or how to contribute, please use the [mailing list](https://groups.google.com/group/eslint) or [chat](https://gitter.im/eslint/eslint) instead of filing an issue.

View File

@ -0,0 +1,21 @@
# Rule Changes
Occasionally, a core ESLint rule needs to be changed. This is not necessarily a bug, but rather, an enhancement that makes a rule more configurable. In those situations, we will consider making changes to rules.
## Proposing a Rule Change
To propose a change to an existing rule, [create a pull request](/docs/developer-guide/contributing/pull-requests.md) or [new issue](https://github.com/eslint/eslint/issues/new?template=RULE_CHANGE.md) and fill out the template.
We need all of this information in order to determine whether or not the change is a good candidate for inclusion.
## Accepting a Rule Change
In order for a rule change to be accepted into ESLint, it must:
1. Adhere to the [Core Rule Guidelines](new-rules.md#core-rule-guidelines)
1. Have an ESLint team member champion the change
1. Be important enough that rule is deemed incomplete without this change
## Implementation is Your Responsibility
The ESLint team doesn't implement rule changes that are suggested by users because we have a limited number of people and need to focus on the overall roadmap. Once a rule change is accepted, you are responsible for implementing and documenting it. You may, alternately, recruit another person to help you. The ESLint team member who championed the rule is your resource to help guide you through the rest of this process.

View File

@ -0,0 +1,36 @@
# Working on Issues
Our public [issues tracker](https://github.com/eslint/eslint/issues) lists all of the things we plan on doing as well as suggestions from the community. Before starting to work on an issue, be sure you read through the rest of this page.
## Issue Labels
We use labels to indicate the status of issues. The most complete documentation on the labels is found in the [Maintainer Guide](https://eslint.org/docs/maintainer-guide/issues.html#when-an-issue-is-opened), but most contributors should find the information on this page sufficient. The most important questions that labels can help you, as a contributor, answer are:
1. Is this issue available for me to work on? If you have little or no experience contributing to ESLint, the [`good first issue`](https://github.com/eslint/eslint/labels/good%20first%20issue) label marks appropriate issues. Otherwise, the [`help wanted`](https://github.com/eslint/eslint/labels/help%20wanted) label is an invitation to work on the issue. If you have more experience, you can try working on other issues labeled [`accepted`](https://github.com/eslint/eslint/labels/accepted). Conversely, issues not yet ready to work on are labeled `triage`, `evaluating`, and/or `needs bikeshedding`, and issues that cannot currently be worked on because of something else, such as a bug in a dependency, are labeled `blocked`.
1. What is this issue about? Labels describing the nature of issues include `bug`, `enhancement`, `feature`, `question`, `rule`, `documentation`, `core`, `build`, `cli`, `infrastructure`, `breaking`, and `chore`. These are documented in the [Maintainer Guide](https://eslint.org/docs/maintainer-guide/issues.html#types-of-issues).
1. What is the priority of this issue? Because we have a lot of issues, we prioritize certain issues above others. The following is the list of priorities, from highest to lowest:
1. **Bugs** - problems with the project are actively affecting users. We want to get these resolved as quickly as possible.
1. **Documentation** - documentation issues are a type of bug in that they actively affect current users. As such, we want to address documentation issues as quickly as possible.
1. **Features** - new functionality that will aid users in the future.
1. **Enhancements** - requested improvements for existing functionality.
1. **Other** - anything else.
Some issues have had monetary rewards attached to them. Those are labeled `bounty`. Bounties are assigned via [BountySource](https://www.bountysource.com/teams/eslint/issues).
## Starting Work
If you're going to work on an issue, please add a comment to that issue saying so and indicating when you think you will complete it. It will help us to avoid duplication of effort. Some examples of good comments are:
* "I'll take a look at this over the weekend."
* "I'm going to do this, give me two weeks."
* "Working on this" (as in, I'm working on it right now)
If an issue has already been claimed by someone, please be respectful of that person's desire to complete the work and don't work on it unless you verify that they are no longer interested.
If you find you can't finish the work, then simply add a comment letting people know, for example:
* "Sorry, it looks like I don't have time to do this."
* "I thought I knew enough to fix this, but it turns out I don't."
No one will blame you for backing out of an issue if you are unable to complete it. We just want to keep the process moving along as efficiently as possible.

View File

@ -0,0 +1,107 @@
# Development Environment
ESLint has a very lightweight development environment that makes updating code fast and easy. This is a step-by-step guide to setting up a local development environment that will let you contribute back to the project.
## Step 1: Install Node.js
Go to <https://nodejs.org/> to download and install the latest stable version for your operating system.
Most of the installers come with [npm](https://www.npmjs.com/) already installed, but if for some reason it doesn't work on your system, you can install it manually using the instructions on the site.
## Step 2: Fork and checkout your own ESLint repository
Go to <https://github.com/eslint/eslint> and click the "Fork" button. Follow the [GitHub documentation](https://help.github.com/articles/fork-a-repo) for forking and cloning.
Once you've cloned the repository, run `npm install` to get all the necessary dependencies:
```
$ cd eslint
$ npm install
```
You must be connected to the Internet for this step to work. You'll see a lot of utilities being downloaded.
## Step 3: Add the upstream source
The *upstream source* is the main ESLint repository that active development happens on. While you won't have push access to upstream, you will have pull access, allowing you to pull in the latest code whenever you want.
To add the upstream source for ESLint, run the following in your repository:
```
git remote add upstream git@github.com:eslint/eslint.git
```
Now, the remote `upstream` points to the upstream source.
## Step 4: Install the Yeoman Generator
[Yeoman](http://yeoman.io) is a scaffold generator that ESLint uses to help streamline development of new rules. If you don't already have Yeoman installed, you can install it via npm:
npm install -g yo
Then, you can install the ESLint Yeoman generator:
npm install -g generator-eslint
Please see the [generator documentation](https://github.com/eslint/generator-eslint) for instructions on how to use it.
## Step 5: Run the tests
Running the tests is the best way to ensure you have correctly set up your development environment. Make sure you're in the `eslint` directory and run:
```
npm test
```
The testing takes a few minutes to complete. If any tests fail, that likely means one or more parts of the environment setup didn't complete correctly. The upstream tests always pass.
## Reference Information
### Workflow
Once you have your development environment installed, you can make and submit changes to the ESLint source files. Doing this successfully requires careful adherence to our [pull-request submission workflow](contributing/pull-requests.md).
### Build Scripts
ESLint has several build scripts that help with various parts of development.
#### npm test
The primary script to use is `npm test`, which does several things:
1. Lints all JavaScript (including tests) and JSON
1. Runs all tests on Node.js
1. Checks code coverage targets
1. Generates `build/eslint.js` for use in a browser
1. Runs a subset of tests in PhantomJS
Be sure to run this after making changes and before sending a pull request with your changes.
**Note:** The full code coverage report is output into `/coverage`.
#### npm run lint
Runs just the JavaScript and JSON linting on the repository
#### npm run webpack
Generates `build/eslint.js`, a version of ESLint for use in the browser
#### npm run docs
Generates JSDoc documentation and places it into `/jsdoc`.
#### npm run profile
This command is used for intensive profiling of ESLint using Chrome Developer Tools. It starts a development server that runs through three profiles:
* Large - Runs ESLint on JSHint
* Medium - Runs ESLint on jQuery
* Small - Runs ESLint on KnockoutJS
Your browser should automatically open to the page in question. When that happens:
1. Open up developer tools
1. Click on Profiles
You should start to see profiles for each run show up on the left side. If not, reload the page in the browser. Once all three profiles have completed, they will be available for inspection.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,386 @@
# ScopeManager
This document was written based on the implementation of [eslint-scope](https://github.com/eslint/eslint-scope), a fork of [escope](https://github.com/estools/escope), and deprecates some members ESLint is not using.
----
## ScopeManager interface
`ScopeManager` object has all variable scopes.
### Fields
#### scopes
* **Type:** `Scope[]`
* **Description:** All scopes.
#### globalScope
* **Type:** `Scope`
* **Description:** The root scope.
### Methods
#### acquire(node, inner = false)
* **Parameters:**
* `node` (`ASTNode`) ... An AST node to get their scope.
* `inner` (`boolean`) ... If the node has multiple scope, this returns the outermost scope normally. If `inner` is `true` then this returns the innermost scope. Default is `false`.
* **Return type:** `Scope | null`
* **Description:** Get the scope of a given AST node. The gotten scope's `block` property is the node. This method never returns `function-expression-name` scope. If the node does not have their scope, this returns `null`.
#### getDeclaredVariables(node)
* **Parameters:**
* `node` (`ASTNode`) ... An AST node to get their variables.
* **Return type:** `Variable[]`
* **Description:** Get the variables that a given AST node defines. The gotten variables' `def[].node`/`def[].parent` property is the node. If the node does not define any variable, this returns an empty array.
### Deprecated members
Those members are defined but not used in ESLint.
#### isModule()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this program is module.
#### isImpliedStrict()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this program is strict mode implicitly. I.e., `options.impliedStrict === true`.
#### isStrictModeSupported()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this program supports strict mode. I.e., `options.ecmaVersion >= 5`.
#### acquireAll(node)
* **Parameters:**
* `node` (`ASTNode`) ... An AST node to get their scope.
* **Return type:** `Scope[] | null`
* **Description:** Get the scopes of a given AST node. The gotten scopes' `block` property is the node. If the node does not have their scope, this returns `null`.
----
## Scope interface
`Scope` object has all variables and references in the scope.
### Fields
#### type
* **Type:** `string`
* **Description:** The type of this scope. This is one of `"block"`, `"catch"`, `"class"`, `"for"`, `"function"`, `"function-expression-name"`, `"global"`, `"module"`, `"switch"`, `"with"`
#### isStrict
* **Type:** `boolean`
* **Description:** `true` if this scope is strict mode.
#### upper
* **Type:** `Scope | null`
* **Description:** The parent scope. If this is the global scope then this property is `null`.
#### childScopes
* **Type:** `Scope[]`
* **Description:** The array of child scopes. This does not include grandchild scopes.
#### variableScope
* **Type:** `Scope`
* **Description:** The scope which hosts variables which are defined by `var` declarations.
#### block
* **Type:** `ASTNode`
* **Description:** The AST node which created this scope.
#### variables
* **Type:** `Variable[]`
* **Description:** The array of all variables which are defined on this scope. This does not include variables which are defined in child scopes.
#### set
* **Type:** `Map<string, Variable>`
* **Description:** The map from variable names to variable objects.
> I hope to rename `set` field or replace by a method.
#### references
* **Type:** `Reference[]`
* **Description:** The array of all references on this scope. This does not include references in child scopes.
#### through
* **Type:** `Reference[]`
* **Description:** The array of references which could not be resolved in this scope.
#### functionExpressionScope
* **Type:** `boolean`
* **Description:** `true` if this scope is `"function-expression-name"` scope.
> I hope to deprecate `functionExpressionScope` field as replacing by `scope.type === "function-expression-name"`.
### Deprecated members
Those members are defined but not used in ESLint.
#### taints
* **Type:** `Map<string, boolean>`
* **Description:** The map from variable names to `tainted` flag.
#### dynamic
* **Type:** `boolean`
* **Description:** `true` if this scope is dynamic. I.e., the type of this scope is `"global"` or `"with"`.
#### directCallToEvalScope
* **Type:** `boolean`
* **Description:** `true` if this scope contains `eval()` invocations.
#### thisFound
* **Type:** `boolean`
* **Description:** `true` if this scope contains `this`.
#### resolve(node)
* **Parameters:**
* `node` (`ASTNode`) ... An AST node to get their reference object. The type of the node must be `"Identifier"`.
* **Return type:** `Reference | null`
* **Description:** Returns `this.references.find(r => r.identifier === node)`.
#### isStatic()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** Returns `!this.dynamic`.
#### isArgumentsMaterialized()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this is a `"function"` scope which has used `arguments` variable.
#### isThisMaterialized()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** Returns `this.thisFound`.
#### isUsedName(name)
* **Parameters:**
* `name` (`string`) ... The name to check.
* **Return type:** `boolean`
* **Description:** `true` if a given name is used in variable names or reference names.
----
## Variable interface
`Variable` object is variable's information.
### Fields
#### name
* **Type:** `string`
* **Description:** The name of this variable.
#### identifiers
* **Type:** `ASTNode[]`
* **Description:** The array of `Identifier` nodes which define this variable. If this variable is redeclared, this array includes two or more nodes.
> I hope to deprecate `identifiers` field as replacing by `defs[].name` field.
#### references
* **Type:** `Reference[]`
* **Description:** The array of the references of this variable.
#### defs
* **Type:** `Definition[]`
* **Description:** The array of the definitions of this variable.
### Deprecated members
Those members are defined but not used in ESLint.
#### tainted
* **Type:** `boolean`
* **Description:** The `tainted` flag. (always `false`)
#### stack
* **Type:** `boolean`
* **Description:** The `stack` flag. (I'm not sure what this means.)
----
## Reference interface
`Reference` object is reference's information.
### Fields
#### identifier
* **Type:** `ASTNode`
* **Description:** The `Identifier` node of this reference.
#### from
* **Type:** `Scope`
* **Description:** The `Scope` object that this reference is on.
#### resolved
* **Type:** `Variable | null`
* **Description:** The `Variable` object that this reference refers. If such variable was not defined, this is `null`.
#### writeExpr
* **Type:** `ASTNode | null`
* **Description:** The ASTNode object which is right-hand side.
#### init
* **Type:** `boolean`
* **Description:** `true` if this writing reference is a variable initializer or a default value.
### Methods
#### isWrite()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this reference is writing.
#### isRead()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this reference is reading.
#### isWriteOnly()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this reference is writing but not reading.
#### isReadOnly()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this reference is reading but not writing.
#### isReadWrite()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this reference is reading and writing.
### Deprecated members
Those members are defined but not used in ESLint.
#### tainted
* **Type:** `boolean`
* **Description:** The `tainted` flag. (always `false`)
#### flag
* **Type:** `number`
* **Description:** `1` is reading, `2` is writing, `3` is reading/writing.
#### partial
* **Type:** `boolean`
* **Description:** The `partial` flag.
#### isStatic()
* **Parameters:**
* **Return type:** `boolean`
* **Description:** `true` if this reference is resolved statically.
----
## Definition interface
`Definition` object is variable definition's information.
### Fields
#### type
* **Type:** `string`
* **Description:** The type of this definition. One of `"CatchClause"`, `"ClassName"`, `"FunctionName"`, `"ImplicitGlobalVariable"`, `"ImportBinding"`, `"Parameter"`, and `"Variable"`.
#### name
* **Type:** `ASTNode`
* **Description:** The `Identifier` node of this definition.
#### node
* **Type:** `ASTNode`
* **Description:** The enclosing node of the name.
| type | node |
|:---------------------------|:-----|
| `"CatchClause"` | `CatchClause`
| `"ClassName"` | `ClassDeclaration` or `ClassExpression`
| `"FunctionName"` | `FunctionDeclaration` or `FunctionExpression`
| `"ImplicitGlobalVariable"` | `Program`
| `"ImportBinding"` | `ImportSpecifier`, `ImportDefaultSpecifier`, or `ImportNamespaceSpecifier`
| `"Parameter"` | `FunctionDeclaration`, `FunctionExpression`, or `ArrowFunctionExpression`
| `"Variable"` | `VariableDeclarator`
#### parent
* **Type:** `ASTNode | undefined | null`
* **Description:** The enclosing statement node of the name.
| type | parent |
|:---------------------------|:-------|
| `"CatchClause"` | `null`
| `"ClassName"` | `null`
| `"FunctionName"` | `null`
| `"ImplicitGlobalVariable"` | `null`
| `"ImportBinding"` | `ImportDeclaration`
| `"Parameter"` | `null`
| `"Variable"` | `VariableDeclaration`
### Deprecated members
Those members are defined but not used in ESLint.
#### index
* **Type:** `number | undefined | null`
* **Description:** The index in the declaration statement.
#### kind
* **Type:** `string | undefined | null`
* **Description:** The kind of the declaration statement.

View File

@ -0,0 +1,133 @@
# Selectors
Some rules and APIs allow the use of selectors to query an AST. This page is intended to:
1. Explain what selectors are
1. Describe the syntax for creating selectors
1. Describe what selectors can be used for
## What is a selector?
A selector is a string that can be used to match nodes in an Abstract Syntax Tree (AST). This is useful for describing a particular syntax pattern in your code.
The syntax for AST selectors is similar to the syntax for [CSS selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors). If you've used CSS selectors before, the syntax for AST selectors should be easy to understand.
The simplest selector is just a node type. A node type selector will match all nodes with the given type. For example, consider the following program:
```js
var foo = 1;
bar.baz();
```
The selector "`Identifier`" will match all `Identifier` nodes in the program. In this case, the selector will match the nodes for `foo`, `bar`, and `baz`.
Selectors are not limited to matching against single node types. For example, the selector `VariableDeclarator > Identifier` will match all `Identifier` nodes that have a `VariableDeclarator` as a direct parent. In the program above, this will match the node for `foo`, but not the nodes for `bar` and `baz`.
## What syntax can selectors have?
The following selectors are supported:
* AST node type: `ForStatement`
* wildcard (matches all nodes): `*`
* attribute existence: `[attr]`
* attribute value: `[attr="foo"]` or `[attr=123]`
* attribute regex: `[attr=/foo.*/]`
* attribute conditions: `[attr!="foo"]`, `[attr>2]`, `[attr<3]`, `[attr>=2]`, or `[attr<=3]`
* nested attribute: `[attr.level2="foo"]`
* field: `FunctionDeclaration > Identifier.id`
* First or last child: `:first-child` or `:last-child`
* nth-child (no ax+b support): `:nth-child(2)`
* nth-last-child (no ax+b support): `:nth-last-child(1)`
* descendant: `FunctionExpression ReturnStatement`
* child: `UnaryExpression > Literal`
* following sibling: `ArrayExpression > Literal + SpreadElement`
* adjacent sibling: `VariableDeclaration ~ VariableDeclaration`
* negation: `:not(ForStatement)`
* matches-any: `:matches([attr] > :first-child, :last-child)`
* class of AST node: `:statement`, `:expression`, `:declaration`, `:function`, or `:pattern`
This syntax is very powerful, and can be used to precisely select many syntactic patterns in your code.
<sup>The examples in this section were adapted from the [esquery](https://github.com/estools/esquery) documentation.</sup>
## What can selectors be used for?
If you're writing custom ESLint rules, you might be interested in using selectors to examine specific parts of the AST. If you're configuring ESLint for your codebase, you might be interested in restricting particular syntax patterns with selectors.
### Listening for selectors in rules
When writing a custom ESLint rule, you can listen for nodes that match a particular selector as the AST is traversed.
```js
module.exports = {
create(context) {
// ...
return {
// This listener will be called for all IfStatement nodes with blocks.
"IfStatement > BlockStatement": function(blockStatementNode) {
// ...your logic here
},
// This listener will be called for all function declarations with more than 3 parameters.
"FunctionDeclaration[params.length>3]": function(functionDeclarationNode) {
// ...your logic here
}
};
}
};
```
Adding `:exit` to the end of a selector will cause the listener to be called when the matching nodes are exited during traversal, rather than when they are entered.
If two or more selectors match the same node, their listeners will be called in order of increasing specificity. The specificity of an AST selector is similar to the specificity of a CSS selector:
* When comparing two selectors, the selector that contains more class selectors, attribute selectors, and pseudo-class selectors (excluding `:not()`) has higher specificity.
* If the class/attribute/pseudo-class count is tied, the selector that contains more node type selectors has higher specificity.
If multiple selectors have equal specificity, their listeners will be called in alphabetical order for that node.
### Restricting syntax with selectors
With the [no-restricted-syntax](/docs/rules/no-restricted-syntax.md) rule, you can restrict the usage of particular syntax in your code. For example, you can use the following configuration to disallow using `if` statements that do not have block statements as their body:
```json
{
"rules": {
"no-restricted-syntax": ["error", "IfStatement > :not(BlockStatement).consequent"]
}
}
```
...or equivalently, you can use this configuration:
```json
{
"rules": {
"no-restricted-syntax": ["error", "IfStatement[consequent.type!='BlockStatement']"]
}
}
```
As another example, you can disallow calls to `require()`:
```json
{
"rules": {
"no-restricted-syntax": ["error", "CallExpression[callee.name='require']"]
}
}
```
Or you can enforce that calls to `setTimeout` always have two arguments:
```json
{
"rules": {
"no-restricted-syntax": ["error", "CallExpression[callee.name='setTimeout'][arguments.length!=2]"]
}
}
```
Using selectors in the `no-restricted-syntax` rule can give you a lot of control over problematic patterns in your codebase, without needing to write custom rules to detect each pattern.

View File

@ -0,0 +1,209 @@
# Shareable Configs
The configuration that you have in your `.eslintrc` file is an important part of your project, and as such, you may want to share it with other projects or people. Shareable configs allow you to publish your configuration settings on [npm](https://www.npmjs.com/) and have others download and use it in their ESLint projects.
## Creating a Shareable Config
Shareable configs are simply npm packages that export a configuration object. To start, [create a Node.js module](https://docs.npmjs.com/getting-started/creating-node-modules) like you normally would. Make sure the module name begins with `eslint-config-`, such as `eslint-config-myconfig`.
npm [scoped modules](https://docs.npmjs.com/misc/scope) are also supported, by naming or prefixing the module with `@scope/eslint-config`, such as `@scope/eslint-config` or `@scope/eslint-config-myconfig`.
Create a new `index.js` file and export an object containing your settings:
```js
module.exports = {
globals: {
MyGlobal: true
},
rules: {
semi: [2, "always"]
}
};
```
Since `index.js` is just JavaScript, you can optionally read these settings from a file or generate them dynamically.
## Publishing a Shareable Config
Once your shareable config is ready, you can [publish to npm](https://docs.npmjs.com/getting-started/publishing-npm-packages) to share with others. We recommend using the `eslint` and `eslintconfig` keywords so others can easily find your module.
You should declare your dependency on ESLint in `package.json` using the [peerDependencies](https://docs.npmjs.com/files/package.json#peerdependencies) field. The recommended way to declare a dependency for future proof compatibility is with the ">=" range syntax, using the lowest required ESLint version. For example:
```
"peerDependencies": {
"eslint": ">= 3"
}
```
If your shareable config depends on a plugin, you should also specify it as a `peerDependency` (plugins will be loaded relative to the end user's project, so the end user is required to install the plugins they need). However, if your shareable config depends on a third-party parser or another shareable config, you can specify these packages as `dependencies`.
You can also test your shareable config on your computer before publishing by linking your module globally. Type:
```bash
npm link
```
Then, in your project that wants to use your shareable config, type:
```bash
npm link eslint-config-myconfig
```
Be sure to replace `eslint-config-myconfig` with the actual name of your module.
## Using a Shareable Config
Shareable configs are designed to work with the `extends` feature of `.eslintrc` files. Instead of using a file path for the value of `extends`, use your module name. For example:
```json
{
"extends": "eslint-config-myconfig"
}
```
You can also omit the `eslint-config-` and it will be automatically assumed by ESLint:
```json
{
"extends": "myconfig"
}
```
### npm scoped modules
npm [scoped modules](https://docs.npmjs.com/misc/scope) are also supported in a number of ways.
By using the module name:
```json
{
"extends": "@scope/eslint-config"
}
```
You can also omit the `eslint-config` and it will be automatically assumed by ESLint:
```json
{
"extends": "@scope"
}
```
The module name can also be customized, just note that when using [scoped modules](https://docs.npmjs.com/misc/scope) it is not possible to omit the `eslint-config-` prefix. Doing so would result in package naming conflicts, and thus in resolution errors in most of cases. For example a package named `@scope/eslint-config-myconfig` vs `@scope/my-config`, since both are valid scoped package names, the configuration should be specified as:
```json
{
"extends": "@scope/eslint-config-myconfig"
}
```
You can override settings from the shareable config by adding them directly into your `.eslintrc` file.
## Sharing Multiple Configs
It's possible to share multiple configs in the same npm package. You can specify a default config for the package by following the directions in the first section. You can specify additional configs by simply adding a new file to your npm package and then referencing it from your ESLint config.
As an example, you can create a file called `my-special-config.js` in the root of your npm package and export a config, such as:
```js
module.exports = {
rules: {
quotes: [2, "double"]
}
};
```
Then, assuming you're using the package name `eslint-config-myconfig`, you can access the additional config via:
```json
{
"extends": "myconfig/my-special-config"
}
```
When using [scoped modules](https://docs.npmjs.com/misc/scope) it is not possible to omit the `eslint-config` namespace. Doing so would result in resolution errors as explained above. Assuming the package name is `@scope/eslint-config`, the additional config can be accessed as:
```json
{
"extends": "@scope/eslint-config/my-special-config"
}
```
Note that you can leave off the `.js` from the filename. In this way, you can add as many additional configs to your package as you'd like.
**Important:** We strongly recommend always including a default config for your plugin to avoid errors.
## Local Config File Resolution
If you need to make multiple configs that can extend from each other and live in different directories, you can create a single shareable config that handles this scenario.
As an example, let's assume you're using the package name `eslint-config-myconfig` and your package looks something like this:
```text
myconfig
├── index.js
└─┬ lib
├── defaults.js
├── dev.js
├── ci.js
└─┬ ci
├── frontend.js
├── backend.js
└── common.js
```
In your `index.js` you can do something like this:
```js
module.exports = require('./lib/ci.js');
```
Now inside your package you have `/lib/defaults.js`, which contains:
```js
module.exports = {
rules: {
'no-console': 1
}
};
```
Inside your `/lib/ci.js` you have
```js
module.exports = require('./ci/backend');
```
Inside your `/lib/ci/common.js`
```js
module.exports = {
rules: {
'no-alert': 2
},
extends: 'myconfig/lib/defaults'
};
```
Despite being in an entirely different directory, you'll see that all `extends` must use the full package path to the config file you wish to extend.
Now inside your `/lib/ci/backend.js`
```js
module.exports = {
rules: {
'no-console': 1
},
extends: 'myconfig/lib/ci/common'
};
```
In the last file, you'll once again see that to properly resolve your config, you'll need include the full package path.
## Further Reading
* [npm Developer Guide](https://docs.npmjs.com/misc/developers)

View File

@ -0,0 +1,40 @@
# Source Code
ESLint is hosted at [GitHub](https://github.com/eslint/eslint) and uses [Git](https://git-scm.com/) for source control. In order to obtain the source code, you must first install Git on your system. Instructions for installing and setting up Git can be found at [https://help.github.com/articles/set-up-git/](https://help.github.com/articles/set-up-git/).
If you simply want to create a local copy of the source to play with, you can clone the main repository using this command:
git clone git://github.com/eslint/eslint.git
If you're planning on contributing to ESLint, then it's a good idea to fork the repository. You can find instructions for forking a repository at [https://help.github.com/articles/fork-a-repo/](https://help.github.com/articles/fork-a-repo/). After forking the ESLint repository, you'll want to create a local copy of your fork.
## Start Developing
Before you can get started developing, you'll need to have a couple of things installed:
* [Node.JS](https://nodejs.org)
* [npm](https://www.npmjs.com/)
Once you have a local copy and have Node.JS and npm installed, you'll need to install the ESLint dependencies:
cd eslint
npm install
Now when you run `eslint`, it will be running your local copy and showing your changes.
**Note:** It's a good idea to re-rerun `npm install` whenever you pull from the main repository to ensure you have the latest development dependencies.
## Directory structure
The ESLint directory and file structure is as follows:
* `bin` - executable files that are available when ESLint is installed
* `conf` - default configuration information
* `docs` - documentation for the project
* `lib` - contains the source code
* `formatters` - all source files defining formatters
* `rules` - all source files defining rules
* `tests` - the main unit test folder
* `lib` - tests for the source code
* `formatters` - tests for the formatters
* `rules` - tests for the rules

View File

@ -0,0 +1,21 @@
# Unit Tests
Most parts of ESLint have unit tests associated with them. Unit tests are written using [Mocha](https://mochajs.org/) and are required when making contributions to ESLint. You'll find all of the unit tests in the `tests` directory.
When you first get the source code, you need to run `npm install` once initially to set ESLint for development. Once you've done that, you can run the tests via:
npm test
This automatically starts Mocha and runs all tests in the `tests` directory. You need only add yours and it will automatically be picked up when running tests.
## Running Individual Tests
If you want to quickly run just one test, you can do so by running Mocha directly and passing in the filename. For example:
npm run test:cli tests/lib/rules/no-wrap-func.js
Running individual tests is useful when you're working on a specific bug and iterating on the solution. You should be sure to run `npm test` before submitting a pull request.
## More Control on Unit Testing
`npm run test:cli` is an alias of the Mocha cli in `./node_modules/.bin/mocha`. [Options](https://mochajs.org/#command-line-usage) are available to be provided to help to better control the test to run.

View File

@ -0,0 +1,368 @@
# Working with Custom Formatters
While ESLint has some built-in formatters available to format the linting results, it's also possible to create and distribute your own custom formatters. You can include custom formatters in your project directly or create an npm package to distribute them separately.
Each formatter is just a function that receives a `results` object and returns a string. For example, the following is how the `json` built-in formatter is implemented:
```js
//my-awesome-formatter.js
module.exports = function(results) {
return JSON.stringify(results, null, 2);
};
```
To run ESLint with this formatter, you can use the `-f` (or `--formatter`) command line flag:
```bash
eslint -f ./my-awesome-formatter.js src/
```
In order to use a local file as a custom formatter, you must begin the filename with a dot (such as `./my-awesome-formatter.js` or `../formatters/my-awesome-formatter.js`).
### The `data` Argument
The exported function receives an optional second argument named `data`. The `data` object provides extended information related to the analysis results. Currently, the `data` object consists of a single property named `rulesMeta`. This property is a dictionary of rule metadata, keyed with `ruleId`. The value for each entry is the `meta` property from the corresponding rule object. The dictionary contains an entry for each rule that was run during the analysis.
Here's what the `data` object would look like if one rule, `no-extra-semi`, had been run:
```js
{
rulesMeta: {
"no-extra-semi": {
type: "suggestion",
docs: {
description: "disallow unnecessary semicolons",
category: "Possible Errors",
recommended: true,
url: "https://eslint.org/docs/rules/no-extra-semi"
},
fixable: "code",
schema: [],
messages: {
unexpected: "Unnecessary semicolon."
}
}
}
}
```
The [Using Rule metadata](#using-rule-metadata) example shows how to use the `data` object in a custom formatter. See the [Working with Rules](https://eslint.org/docs/developer-guide/working-with-rules) page for more information about rules.
## Packaging the Custom Formatter
Custom formatters can also be distributed through npm packages. To do so, create an npm package with a name in the format of `eslint-formatter-*`, where `*` is the name of your formatter (such as `eslint-formatter-awesome`). Projects should then install the package and can use the custom formatter with the `-f` (or `--formatter`) flag like this:
```bash
eslint -f awesome src/
```
Because ESLint knows to look for packages beginning with `eslint-formatter-` when the specified formatter doesn't begin with a dot, there is no need to type `eslint-formatter-` when using a packaged custom formatter.
Tips for `package.json`:
* The `main` entry should be the JavaScript file implementing your custom formatter.
* Add these `keywords` to help users find your formatter:
* `"eslint"`
* `"eslint-formatter"`
* `"eslintformatter"`
See all [formatters on npm](https://www.npmjs.com/search?q=eslint-formatter);
## The `results` Object
The `results` object passed into a formatter is an array of objects containing the lint results for individual files. Here's some example output:
```js
[
{
filePath: "path/to/file.js",
messages: [
{
ruleId: "curly",
severity: 2,
message: "Expected { after 'if' condition.",
line: 2,
column: 1,
nodeType: "IfStatement"
},
{
ruleId: "no-process-exit",
severity: 2,
message: "Don't use process.exit(); throw an error instead.",
line: 3,
column: 1,
nodeType: "CallExpression"
}
],
errorCount: 2,
warningCount: 0,
fixableErrorCount: 0,
fixableWarningCount: 0,
source:
"var err = doStuff();\nif (err) console.log('failed tests: ' + err);\nprocess.exit(1);\n"
},
{
filePath: "Gruntfile.js",
messages: [],
errorCount: 0,
warningCount: 0,
fixableErrorCount: 0,
fixableWarningCount: 0
}
]
```
### The `result` Object
<!-- This section is copied from the "Node.js API" page. Changes to this section should
also be manually applied to that page. -->
Each object in the `results` array is a `result` object. Each `result` object contains the path of the file that was linted and information about linting issues that were encountered. Here are the properties available on each `result` object:
* **filePath**: The absolute path to the file that was linted.
* **messages**: An array of `message` objects. See below for more info about messages.
* **errorCount**: The number of errors for the given file.
* **warningCount**: The number of warnings for the given file.
* **source**: The source code for the given file. This property is omitted if this file has no errors/warnings or if the `output` property is present.
* **output**: The source code for the given file with as many fixes applied as possible. This property is omitted if no fix is available.
### The `message` Object
Each `message` object contains information about the ESLint rule that was triggered by some source code. The properties available on each `message` object are:
* **ruleId**: the ID of the rule that produced the error or warning.
* **severity**: the severity of the failure, `1` for warnings and `2` for errors.
* **message**: the human readable description of the error.
* **line**: the line where the issue is located.
* **column**: the column where the issue is located.
* **nodeType**: the type of the node in the [AST](https://github.com/estree/estree/blob/master/spec.md#node-objects)
## Examples
### Summary formatter
A formatter that only cares about the total count of errors and warnings will look like this:
```javascript
module.exports = function(results) {
// accumulate the errors and warnings
var summary = results.reduce(
function(seq, current) {
seq.errors += current.errorCount;
seq.warnings += current.warningCount;
return seq;
},
{ errors: 0, warnings: 0 }
);
if (summary.errors > 0 || summary.warnings > 0) {
return (
"Errors: " +
summary.errors +
", Warnings: " +
summary.warnings +
"\n"
);
}
return "";
};
```
Running `eslint` with the previous custom formatter,
```bash
eslint -f ./my-awesome-formatter.js src/
```
Will produce the following output:
```bash
Errors: 2, Warnings: 4
```
### Detailed formatter
A more complex report will look something like this:
```javascript
module.exports = function(results, data) {
var results = results || [];
var summary = results.reduce(
function(seq, current) {
current.messages.forEach(function(msg) {
var logMessage = {
filePath: current.filePath,
ruleId: msg.ruleId,
ruleUrl: data.rulesMeta[msg.ruleId].url,
message: msg.message,
line: msg.line,
column: msg.column
};
if (msg.severity === 1) {
logMessage.type = "warning";
seq.warnings.push(logMessage);
}
if (msg.severity === 2) {
logMessage.type = "error";
seq.errors.push(logMessage);
}
});
return seq;
},
{
errors: [],
warnings: []
}
);
if (summary.errors.length > 0 || summary.warnings.length > 0) {
var lines = summary.errors
.concat(summary.warnings)
.map(function(msg) {
return (
"\n" +
msg.type +
" " +
msg.ruleId + (msg.ruleUrl ? " (" + msg.ruleUrl + ")" : ""
"\n " +
msg.filePath +
":" +
msg.line +
":" +
msg.column
);
})
.join("\n");
return lines + "\n";
}
};
```
So running `eslint` with this custom formatter:
```bash
eslint -f ./my-awesome-formatter.js src/
```
The output will be
```bash
error space-infix-ops (https://eslint.org/docs/rules/space-infix-ops)
src/configs/bundler.js:6:8
error semi (https://eslint.org/docs/rules/semi)
src/configs/bundler.js:6:10
warning no-unused-vars (https://eslint.org/docs/rules/no-unused-vars)
src/configs/bundler.js:5:6
warning no-unused-vars (https://eslint.org/docs/rules/no-unused-vars)
src/configs/bundler.js:6:6
warning no-shadow (https://eslint.org/docs/rules/no-shadow)
src/configs/bundler.js:65:32
warning no-unused-vars (https://eslint.org/docs/rules/no-unused-vars)
src/configs/clean.js:3:6
```
## Passing Arguments to Formatters
While custom formatter do not receive arguments in addition to the results object, it is possible to pass additional data into formatters.
## Using Environment Variables
Custom formatters have access to environment variables and so can change their behavior based on environment variable data. Here's an example that uses a `AF_SKIP_WARNINGS` environment variable to determine whether or not to show warnings in the results:
```js
module.exports = function(results) {
var skipWarnings = process.env.AF_SKIP_WARNINGS === "true"; //af stands for awesome-formatter
var results = results || [];
var summary = results.reduce(
function(seq, current) {
current.messages.forEach(function(msg) {
var logMessage = {
filePath: current.filePath,
ruleId: msg.ruleId,
message: msg.message,
line: msg.line,
column: msg.column
};
if (msg.severity === 1) {
logMessage.type = "warning";
seq.warnings.push(logMessage);
}
if (msg.severity === 2) {
logMessage.type = "error";
seq.errors.push(logMessage);
}
});
return seq;
},
{
errors: [],
warnings: []
}
);
if (summary.errors.length > 0 || summary.warnings.length > 0) {
var warnings = !skipWarnings ? summary.warnings : []; // skip the warnings in that case
var lines = summary.errors
.concat(warnings)
.map(function(msg) {
return (
"\n" +
msg.type +
" " +
msg.ruleId +
"\n " +
msg.filePath +
":" +
msg.line +
":" +
msg.column
);
})
.join("\n");
return lines + "\n";
}
};
```
You would run ESLint with this custom formatter and an environment variable set like this:
```bash
AF_SKIP_WARNINGS=true eslint -f ./my-awesome-formatter.js src/
```
The output would be:
```bash
error space-infix-ops
src/configs/bundler.js:6:8
error semi
src/configs/bundler.js:6:10
```
### Complex Argument Passing
If you find the custom formatter pattern doesn't provide enough options for the way you'd like to format ESLint results, the best option is to use ESLint's built-in [JSON formatter](https://eslint.org/docs/user-guide/formatters/) and pipe the output to a second program. For example:
```bash
eslint -f json src/ | your-program-that-reads-JSON --option
```
In this example, the `your-program-that-reads-json` program can accept the raw JSON of ESLint results and process it before outputting its own format of the results. You can pass as many command line arguments to that program as are necessary to customize the output.
## Note: Formatting for Terminals
Modern terminals like [iTerm2](https://www.iterm2.com/) or [Guake](http://guake-project.org/) expect a specific results format to automatically open filenames when they are clicked. Most terminals support this format for that purpose:
```bash
file:line:column
```

View File

@ -0,0 +1,73 @@
# Working with Custom Parsers
If you want to use your own parser and provide additional capabilities for your rules, you can specify your own custom parser. If a `parseForESLint` method is exposed on the parser, this method will be used to parse the code. Otherwise, the `parse` method will be used. Both methods should take in the source code as the first argument, and an optional configuration object as the second argument (provided as `parserOptions` in a config file). The `parse` method should simply return the AST. The `parseForESLint` method should return an object that contains the required property `ast` and optional properties `services`, `scopeManager`, and `visitorKeys`.
* `ast` should contain the AST.
* `services` can contain any parser-dependent services (such as type checkers for nodes). The value of the `services` property is available to rules as `context.parserServices`. Default is an empty object.
* `scopeManager` can be a [ScopeManager](./scope-manager-interface.md) object. Custom parsers can use customized scope analysis for experimental/enhancement syntaxes. Default is the `ScopeManager` object which is created by [eslint-scope](https://github.com/eslint/eslint-scope).
* Support for `scopeManager` was added in ESLint v4.14.0. ESLint versions which support `scopeManager` will provide an `eslintScopeManager: true` property in `parserOptions`, which can be used for feature detection.
* `visitorKeys` can be an object to customize AST traversal. The keys of the object are the type of AST nodes. Each value is an array of the property names which should be traversed. Default is [KEYS of `eslint-visitor-keys`](https://github.com/eslint/eslint-visitor-keys#evkkeys).
* Support for `visitorKeys` was added in ESLint v4.14.0. ESLint versions which support `visitorKeys` will provide an `eslintVisitorKeys: true` property in `parserOptions`, which can be used for feature detection.
You can find an ESLint parser project [here](https://github.com/typescript-eslint/typescript-eslint).
```json
{
"parser": "./path/to/awesome-custom-parser.js"
}
```
```javascript
var espree = require("espree");
// awesome-custom-parser.js
exports.parseForESLint = function(code, options) {
return {
ast: espree.parse(code, options),
services: {
foo: function() {
console.log("foo");
}
},
scopeManager: null,
visitorKeys: null
};
};
```
## The AST specification
The AST that custom parsers should create is based on [ESTree](https://github.com/estree/estree). The AST requires some additional properties about detail information of the source code.
### All nodes:
All nodes must have `range` property.
* `range` (`number[]`) is an array of two numbers. Both numbers are a 0-based index which is the position in the array of source code characters. The first is the start position of the node, the second is the end position of the node. `code.slice(node.range[0], node.range[1])` must be the text of the node. This range does not include spaces/parentheses which are around the node.
* `loc` (`SourceLocation`) must not be `null`. [The `loc` property is defined as nullable by ESTree](https://github.com/estree/estree/blob/25834f7247d44d3156030f8e8a2d07644d771fdb/es5.md#node-objects), but ESLint requires this property. On the other hand, `SourceLocation#source` property can be `undefined`. ESLint does not use the `SourceLocation#source` property.
The `parent` property of all nodes must be rewritable. ESLint sets each node's `parent` property to its parent node while traversing, before any rules have access to the AST.
### The `Program` node:
The `Program` node must have `tokens` and `comments` properties. Both properties are an array of the below Token interface.
```ts
interface Token {
type: string;
loc: SourceLocation;
range: [number, number]; // See "All nodes:" section for details of `range` property.
value: string;
}
```
* `tokens` (`Token[]`) is the array of tokens which affect the behavior of programs. Arbitrary spaces can exist between tokens, so rules check the `Token#range` to detect spaces between tokens. This must be sorted by `Token#range[0]`.
* `comments` (`Token[]`) is the array of comment tokens. This must be sorted by `Token#range[0]`.
The range indexes of all tokens and comments must not overlap with the range of other tokens and comments.
### The `Literal` node:
The `Literal` node must have `raw` property.
* `raw` (`string`) is the source code of this literal. This is the same as `code.slice(node.range[0], node.range[1])`.

View File

@ -0,0 +1,232 @@
# Working with Plugins
Each plugin is an npm module with a name in the format of `eslint-plugin-<plugin-name>`, such as `eslint-plugin-jquery`. You can also use scoped packages in the format of `@<scope>/eslint-plugin-<plugin-name>` such as `@jquery/eslint-plugin-jquery` or even `@<scope>/eslint-plugin` such as `@jquery/eslint-plugin`.
## Create a Plugin
The easiest way to start creating a plugin is to use the [Yeoman generator](https://www.npmjs.com/package/generator-eslint). The generator will guide you through setting up the skeleton of a plugin.
### Rules in Plugins
Plugins can expose additional rules for use in ESLint. To do so, the plugin must export a `rules` object containing a key-value mapping of rule ID to rule. The rule ID does not have to follow any naming convention (so it can just be `dollar-sign`, for instance).
```js
module.exports = {
rules: {
"dollar-sign": {
create: function (context) {
// rule implementation ...
}
}
}
};
```
To use the rule in ESLint, you would use the unprefixed plugin name, followed by a slash, followed by the rule name. So if this plugin were named `eslint-plugin-myplugin`, then in your configuration you'd refer to the rule by the name `myplugin/dollar-sign`. Example: `"rules": {"myplugin/dollar-sign": 2}`.
### Environments in Plugins
Plugins can expose additional environments for use in ESLint. To do so, the plugin must export an `environments` object. The keys of the `environments` object are the names of the different environments provided and the values are the environment settings. For example:
```js
module.exports = {
environments: {
jquery: {
globals: {
$: false
}
}
}
};
```
There's a `jquery` environment defined in this plugin. To use the environment in ESLint, you would use the unprefixed plugin name, followed by a slash, followed by the environment name. So if this plugin were named `eslint-plugin-myplugin`, then you would set the environment in your configuration to be `"myplugin/jquery"`.
Plugin environments can define the following objects:
1. `globals` - acts the same `globals` in a configuration file. The keys are the names of the globals and the values are `true` to allow the global to be overwritten and `false` to disallow.
1. `parserOptions` - acts the same as `parserOptions` in a configuration file.
### Processors in Plugins
You can also create plugins that would tell ESLint how to process files other than JavaScript. In order to create a processor, the object that is exported from your module has to conform to the following interface:
```js
module.exports = {
processors: {
"processor-name": {
// takes text of the file and filename
preprocess: function(text, filename) {
// here, you can strip out any non-JS content
// and split into multiple strings to lint
return [ // return an array of code blocks to lint
{ text: code1, filename: "0.js" },
{ text: code2, filename: "1.js" },
];
},
// takes a Message[][] and filename
postprocess: function(messages, filename) {
// `messages` argument contains two-dimensional array of Message objects
// where each top-level array item contains array of lint messages related
// to the text that was returned in array from preprocess() method
// you need to return a one-dimensional array of the messages you want to keep
return [].concat(...messages);
},
supportsAutofix: true // (optional, defaults to false)
}
}
};
```
**The `preprocess` method** takes the file contents and filename as arguments, and returns an array of code blocks to lint. The code blocks will be linted separately but still be registered to the filename.
A code block has two properties `text` and `filename`; the `text` property is the content of the block and the `filename` property is the name of the block. Name of the block can be anything, but should include the file extension, that would tell the linter how to process the current block. The linter will check [`--ext` CLI option](../user-guide/command-line-interface.md#--ext) to see if the current block should be linted, and resolve `overrides` configs to check how to process the current block.
It's up to the plugin to decide if it needs to return just one part, or multiple pieces. For example in the case of processing `.html` files, you might want to return just one item in the array by combining all scripts, but for `.md` file where each JavaScript block might be independent, you can return multiple items.
**The `postprocess` method** takes a two-dimensional array of arrays of lint messages and the filename. Each item in the input array corresponds to the part that was returned from the `preprocess` method. The `postprocess` method must adjust the locations of all errors to correspond to locations in the original, unprocessed code, and aggregate them into a single flat array and return it.
Reported problems have the following location information:
```typescript
{
line: number,
column: number,
endLine?: number,
endColumn?: number
}
```
By default, ESLint will not perform autofixes when a processor is used, even when the `--fix` flag is enabled on the command line. To allow ESLint to autofix code when using your processor, you should take the following additional steps:
1. Update the `postprocess` method to additionally transform the `fix` property of reported problems. All autofixable problems will have a `fix` property, which is an object with the following schema:
```js
{
range: [number, number],
text: string
}
```
The `range` property contains two indexes in the code, referring to the start and end location of a contiguous section of text that will be replaced. The `text` property refers to the text that will replace the given range.
In the initial list of problems, the `fix` property will refer to a fix in the processed JavaScript. The `postprocess` method should transform the object to refer to a fix in the original, unprocessed file.
2. Add a `supportsAutofix: true` property to the processor.
You can have both rules and processors in a single plugin. You can also have multiple processors in one plugin.
To support multiple extensions, add each one to the `processors` element and point them to the same object.
#### Specifying Processor in Config Files
To use a processor, add its ID to a `processor` section in the config file. Processor ID is a concatenated string of plugin name and processor name with a slash as a separator. This can also be added to a `overrides` section of the config, to specify which processors should handle which files.
For example:
```yml
plugins:
- a-plugin
overrides:
- files: "*.md"
processor: a-plugin/markdown
```
See [Specifying Processor](../user-guide/configuring.md#specifying-processor) for details.
#### File Extension-named Processor
If a processor name starts with `.`, ESLint handles the processor as a **file extension-named processor** especially and applies the processor to the kind of files automatically. People don't need to specify the file extension-named processors in their config files.
For example:
```js
module.exports = {
processors: {
// This processor will be applied to `*.md` files automatically.
// Also, people can use this processor as "plugin-id/.md" explicitly.
".md": {
preprocess(text, filename) { /* ... */ },
postprocess(messageLists, filename) { /* ... */ }
}
}
}
```
### Configs in Plugins
You can bundle configurations inside a plugin by specifying them under the `configs` key. This can be useful when you want to provide not just code style, but also some custom rules to support it. Multiple configurations are supported per plugin. Note that it is not possible to specify a default configuration for a given plugin and that users must specify in their configuration file when they want to use one.
```js
// eslint-plugin-myPlugin
module.exports = {
configs: {
myConfig: {
plugins: ["myPlugin"],
env: ["browser"],
rules: {
semi: "error",
"myPlugin/my-rule": "error",
"eslint-plugin-myPlugin/another-rule": "error"
}
},
myOtherConfig: {
plugins: ["myPlugin"],
env: ["node"],
rules: {
"myPlugin/my-rule": "off",
"eslint-plugin-myPlugin/another-rule": "off"
"eslint-plugin-myPlugin/yet-another-rule": "error"
}
}
}
};
```
If the example plugin above were called `eslint-plugin-myPlugin`, the `myConfig` and `myOtherConfig` configurations would then be usable by extending off of `"plugin:myPlugin/myConfig"` and `"plugin:myPlugin/myOtherConfig"`, respectively.
```json
{
"extends": ["plugin:myPlugin/myConfig"]
}
```
**Note:** Please note that configuration will not enable any of the plugin's rules by default, and instead should be treated as a standalone config. This means that you must specify your plugin name in the `plugins` array as well as any rules you want to enable that are part of the plugin. Any plugin rules must be prefixed with the short or long plugin name. See [Configuring Plugins](../user-guide/configuring.md#configuring-plugins) for more information.
### Peer Dependency
To make clear that the plugin requires ESLint to work correctly you have to declare ESLint as a `peerDependency` in your `package.json`.
The plugin support was introduced in ESLint version `0.8.0`. Ensure the `peerDependency` points to ESLint `0.8.0` or later.
```json
{
"peerDependencies": {
"eslint": ">=0.8.0"
}
}
```
### Testing
ESLint provides the [`RuleTester`](/docs/developer-guide/nodejs-api.md#ruletester) utility to make it easy to test the rules of your plugin.
## Share Plugins
In order to make your plugin available to the community you have to publish it on npm.
Recommended keywords:
* `eslint`
* `eslintplugin`
Add these keywords into your `package.json` file to make it easy for others to find.
## Further Reading
* [npm Developer Guide](https://docs.npmjs.com/misc/developers)

View File

@ -0,0 +1,575 @@
# Working with Rules
Each rule in ESLint has two files named with its identifier (for example, `no-extra-semi`).
* in the `lib/rules` directory: a source file (for example, `no-extra-semi.js`)
* in the `tests/lib/rules` directory: a test file (for example, `no-extra-semi.js`)
**Important:** If you submit a **core** rule to the ESLint repository, you **must** follow some conventions explained below.
Here is the basic format of the source file for a rule:
```js
/**
* @fileoverview Rule to disallow unnecessary semicolons
* @author Nicholas C. Zakas
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = function(context) {
return {
// callback functions
};
};
module.exports.schema = []; // no options
```
## Rule Basics
`schema` (array) specifies the [options](#options-schemas) so ESLint can prevent invalid [rule configurations](../user-guide/configuring.md#configuring-rules)
`create` (function) returns an object with methods that ESLint calls to "visit" nodes while traversing the abstract syntax tree (AST as defined by [ESTree](https://github.com/estree/estree)) of JavaScript code:
* if a key is a node type, ESLint calls that **visitor** function while going **down** the tree
* if a key is a node type plus `:exit`, ESLint calls that **visitor** function while going **up** the tree
* if a key is an event name, ESLint calls that **handler** function for [code path analysis](./code-path-analysis.md)
A rule can use the current node and its surrounding tree to report or fix problems.
Here are methods for the [array-callback-return](../rules/array-callback-return.md) rule:
```js
function checkLastSegment (node) {
// report problem for function if last code path segment is reachable
}
module.exports = function(context) {
// declare the state of the rule
return {
ReturnStatement: function(node) {
// at a ReturnStatement node while going down
},
// at a function expression node while going up:
"FunctionExpression:exit": checkLastSegment,
"ArrowFunctionExpression:exit": checkLastSegment,
onCodePathStart: function (codePath, node) {
// at the start of analyzing a code path
},
onCodePathEnd: function(codePath, node) {
// at the end of analyzing a code path
}
};
};
```
## The Context Object
The `context` object contains additional functionality that is helpful for rules to do their jobs. As the name implies, the `context` object contains information that is relevant to the context of the rule. The `context` object has the following properties:
* `parserOptions` - the parser options configured for this run (more details [here](../user-guide/configuring.md#specifying-parser-options)).
* `id` - the rule ID.
* `options` - an array of rule options.
* `settings` - the `settings` from configuration.
* `parserPath` - the full path to the `parser` from configuration.
Additionally, the `context` object has the following methods:
* `getAncestors()` - returns an array of ancestor nodes based on the current traversal.
* `getDeclaredVariables(node)` - returns the declared variables on the given node.
* `getFilename()` - returns the filename associated with the source.
* `getScope()` - returns the current scope.
* `getSourceCode()` - returns a `SourceCode` object that you can use to work with the source that was passed to ESLint
* `markVariableAsUsed(name)` - marks the named variable in scope as used. This affects the [no-unused-vars](../rules/no-unused-vars.md) rule.
* `report(descriptor)` - reports a problem in the code.
**Deprecated:** The following methods on the `context` object are deprecated. Please use the corresponding methods on `SourceCode` instead:
* `getAllComments()` - returns an array of all comments in the source. Use `sourceCode.getAllComments()` instead.
* `getComments(node)` - returns the leading and trailing comments arrays for the given node. Use `sourceCode.getComments(node)` instead.
* `getFirstToken(node)` - returns the first token representing the given node. Use `sourceCode.getFirstToken(node)` instead.
* `getFirstTokens(node, count)` - returns the first `count` tokens representing the given node. Use `sourceCode.getFirstTokens(node, count)` instead.
* `getJSDocComment(node)` - returns the JSDoc comment for a given node or `null` if there is none. Use `sourceCode.getJSDocComment(node)` instead.
* `getLastToken(node)` - returns the last token representing the given node. Use `sourceCode.getLastToken(node)` instead.
* `getLastTokens(node, count)` - returns the last `count` tokens representing the given node. Use `sourceCode.getLastTokens(node, count)` instead.
* `getNodeByRangeIndex(index)` - returns the deepest node in the AST containing the given source index. Use `sourceCode.getNodeByRangeIndex(index)` instead.
* `getSource(node)` - returns the source code for the given node. Omit `node` to get the whole source. Use `sourceCode.getText(node)` instead.
* `getSourceLines()` - returns the entire source code split into an array of string lines. Use `sourceCode.lines` instead.
* `getTokenAfter(nodeOrToken)` - returns the first token after the given node or token. Use `sourceCode.getTokenAfter(nodeOrToken)` instead.
* `getTokenBefore(nodeOrToken)` - returns the first token before the given node or token. Use `sourceCode.getTokenBefore(nodeOrToken)` instead.
* `getTokenByRangeStart(index)` - returns the token whose range starts at the given index in the source. Use `sourceCode.getTokenByRangeStart(index)` instead.
* `getTokens(node)` - returns all tokens for the given node. Use `sourceCode.getTokens(node)` instead.
* `getTokensAfter(nodeOrToken, count)` - returns `count` tokens after the given node or token. Use `sourceCode.getTokensAfter(nodeOrToken, count)` instead.
* `getTokensBefore(nodeOrToken, count)` - returns `count` tokens before the given node or token. Use `sourceCode.getTokensBefore(nodeOrToken, count)` instead.
* `getTokensBetween(node1, node2)` - returns the tokens between two nodes. Use `sourceCode.getTokensBetween(node1, node2)` instead.
* `report(node, [location], message)` - reports a problem in the code.
### context.report()
The main method you'll use is `context.report()`, which publishes a warning or error (depending on the configuration being used). This method accepts a single argument, which is an object containing the following properties:
* `message` - the problem message.
* `node` - (optional) the AST node related to the problem. If present and `loc` is not specified, then the starting location of the node is used as the location of the problem.
* `loc` - (optional) an object specifying the location of the problem. If both `loc` and `node` are specified, then the location is used from `loc` instead of `node`.
* `line` - the 1-based line number at which the problem occurred.
* `column` - the 0-based column number at which the problem occurred.
* `data` - (optional) placeholder data for `message`.
* `fix` - (optional) a function that applies a fix to resolve the problem.
Note that at least one of `node` or `loc` is required.
The simplest example is to use just `node` and `message`:
```js
context.report({
node: node,
message: "Unexpected identifier"
});
```
The node contains all of the information necessary to figure out the line and column number of the offending text as well the source text representing the node.
You can also use placeholders in the message and provide `data`:
```js
{% raw %}
context.report({
node: node,
message: "Unexpected identifier: {{ identifier }}",
data: {
identifier: node.name
}
});
{% endraw %}
```
Note that leading and trailing whitespace is optional in message parameters.
The node contains all of the information necessary to figure out the line and column number of the offending text as well the source text representing the node.
### Applying Fixes
If you'd like ESLint to attempt to fix the problem you're reporting, you can do so by specifying the `fix` function when using `context.report()`. The `fix` function receives a single argument, a `fixer` object, that you can use to apply a fix. For example:
```js
context.report({
node: node,
message: "Missing semicolon".
fix: function(fixer) {
return fixer.insertTextAfter(node, ";");
}
});
```
Here, the `fix()` function is used to insert a semicolon after the node. Note that the fix is not immediately applied and may not be applied at all if there are conflicts with other fixes. If the fix cannot be applied, then the problem message is reported as usual; if the fix can be applied, then the problem message is not reported.
The `fixer` object has the following methods:
* `insertTextAfter(nodeOrToken, text)` - inserts text after the given node or token
* `insertTextAfterRange(range, text)` - inserts text after the given range
* `insertTextBefore(nodeOrToken, text)` - inserts text before the given node or token
* `insertTextBeforeRange(range, text)` - inserts text before the given range
* `remove(nodeOrToken)` - removes the given node or token
* `removeRange(range)` - removes text in the given range
* `replaceText(nodeOrToken, text)` - replaces the text in the given node or token
* `replaceTextRange(range, text)` - replaces the text in the given range
Best practices for fixes:
1. Make fixes that are as small as possible. Anything more than a single character is risky and could prevent other, simpler fixes from being made.
1. Only make one fix per message. This is enforced because you must return the result of the fixer operation from `fix()`.
1. Fixes should not introduce clashes with other rules. You can accidentally introduce a new problem that won't be reported until ESLint is run again. Another good reason to make as small a fix as possible.
### context.options
Some rules require options in order to function correctly. These options appear in configuration (`.eslintrc`, command line, or in comments). For example:
```json
{
"quotes": [2, "double"]
}
```
The `quotes` rule in this example has one option, `"double"` (the `2` is the error level). You can retrieve the options for a rule by using `context.options`, which is an array containing every configured option for the rule. In this case, `context.options[0]` would contain `"double"`:
```js
module.exports = function(context) {
var isDouble = (context.options[0] === "double");
// ...
}
```
Since `context.options` is just an array, you can use it to determine how many options have been passed as well as retrieving the actual options themselves. Keep in mind that the error level is not part of `context.options`, as the error level cannot be known or modified from inside a rule.
When using options, make sure that your rule has some logic defaults in case the options are not provided.
### context.getSourceCode()
The `SourceCode` object is the main object for getting more information about the source code being linted. You can retrieve the `SourceCode` object at any time by using the `getSourceCode()` method:
```js
module.exports = function(context) {
var sourceCode = context.getSourceCode();
// ...
}
```
Once you have an instance of `SourceCode`, you can use the methods on it to work with the code:
* `getAllComments()` - returns an array of all comments in the source.
* `getComments(node)` - returns the leading and trailing comments arrays for the given node.
* `getFirstToken(node)` - returns the first token representing the given node.
* `getFirstTokens(node, count)` - returns the first `count` tokens representing the given node.
* `getJSDocComment(node)` - returns the JSDoc comment for a given node or `null` if there is none.
* `getLastToken(node)` - returns the last token representing the given node.
* `getLastTokens(node, count)` - returns the last `count` tokens representing the given node.
* `getNodeByRangeIndex(index)` - returns the deepest node in the AST containing the given source index.
* `isSpaceBetweenTokens(first, second)` - returns true if there is a whitespace character between the two tokens.
* `getText(node)` - returns the source code for the given node. Omit `node` to get the whole source.
* `getTokenAfter(nodeOrToken)` - returns the first token after the given node or token.
* `getTokenBefore(nodeOrToken)` - returns the first token before the given node or token.
* `getTokenByRangeStart(index)` - returns the token whose range starts at the given index in the source.
* `getTokens(node)` - returns all tokens for the given node.
* `getTokensAfter(nodeOrToken, count)` - returns `count` tokens after the given node or token.
* `getTokensBefore(nodeOrToken, count)` - returns `count` tokens before the given node or token.
* `getTokensBetween(node1, node2)` - returns the tokens between two nodes.
There are also some properties you can access:
* `hasBOM` - the flag to indicate whether or not the source code has Unicode BOM.
* `text` - the full text of the code being linted. Unicode BOM has been stripped from this text.
* `ast` - the `Program` node of the AST for the code being linted.
* `lines` - an array of lines, split according to the specification's definition of line breaks.
You should use a `SourceCode` object whenever you need to get more information about the code being linted.
### Options Schemas
Rules may export a `schema` property, which is a [JSON schema](http://json-schema.org/) format description of a rule's options which will be used by ESLint to validate configuration options and prevent invalid or unexpected inputs before they are passed to the rule in `context.options`.
There are two formats for a rule's exported `schema`. The first is a full JSON Schema object describing all possible options the rule accepts, including the rule's error level as the first argument and any optional arguments thereafter.
However, to simplify schema creation, rules may also export an array of schemas for each optional positional argument, and ESLint will automatically validate the required error level first. For example, the `yoda` rule accepts a primary mode argument, as well as an extra options object with named properties.
```js
// "yoda": [2, "never", { "exceptRange": true }]
module.exports.schema = [
{
"enum": ["always", "never"]
},
{
"type": "object",
"properties": {
"exceptRange": {
"type": "boolean"
}
},
"additionalProperties": false
}
];
```
In the preceding example, the error level is assumed to be the first argument. It is followed by the first optional argument, a string which may be either `"always"` or `"never"`. The final optional argument is an object, which may have a Boolean property named `exceptRange`.
To learn more about JSON Schema, we recommend looking at some [examples](http://json-schema.org/examples.html) to start, and also reading [Understanding JSON Schema](http://spacetelescope.github.io/understanding-json-schema/) (a free ebook).
### Getting the Source
If your rule needs to get the actual JavaScript source to work with, then use the `sourceCode.getText()` method. This method works as follows:
```js
// get all source
var source = sourceCode.getText();
// get source for just this AST node
var nodeSource = sourceCode.getText(node);
// get source for AST node plus previous two characters
var nodeSourceWithPrev = sourceCode.getText(node, 2);
// get source for AST node plus following two characters
var nodeSourceWithFollowing = sourceCode.getText(node, 0, 2);
```
In this way, you can look for patterns in the JavaScript text itself when the AST isn't providing the appropriate data (such as location of commas, semicolons, parentheses, etc.).
### Accessing comments
If you need to access comments for a specific node you can use `sourceCode.getComments(node)`:
```js
// the "comments" variable has a "leading" and "trailing" property containing
// its leading and trailing comments, respectively
var comments = sourceCode.getComments(node);
```
Keep in mind that comments are technically not a part of the AST and are only attached to it on demand, i.e. when you call `getComments()`.
**Note:** One of the libraries adds AST node properties for comments - do not use these properties. Always use `sourceCode.getComments()` as this is the only guaranteed API for accessing comments (we will likely change how comments are handled later).
### Accessing Code Paths
ESLint analyzes code paths while traversing AST.
You can access that code path objects with five events related to code paths.
[details here](./code-path-analysis.md)
## Rule Unit Tests
Each rule must have a set of unit tests submitted with it to be accepted. The test file is named the same as the source file but lives in `tests/lib/`. For example, if your rule source file is `lib/rules/foo.js` then your test file should be `tests/lib/rules/foo.js`.
For your rule, be sure to test:
1. All instances that should be flagged as warnings.
1. At least one pattern that should **not** be flagged as a warning.
The basic pattern for a rule unit test file is:
```js
/**
* @fileoverview Tests for no-with rule.
* @author Nicholas C. Zakas
*/
"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
var rule = require("../../../lib/rules/no-with"),
RuleTester = require("../../../lib/testers/rule-tester");
//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------
var ruleTester = new RuleTester();
ruleTester.run("no-with", rule, {
valid: [
"foo.bar()"
],
invalid: [
{
code: "with(foo) { bar() }",
errors: [{ message: "Unexpected use of 'with' statement.", type: "WithStatement"}]
}
]
});
```
Be sure to replace the value of `"no-with"` with your rule's ID. There are plenty of examples in the `tests/lib/rules/` directory.
### Valid Code
Each valid case can be either a string or an object. The object form is used when you need to specify additional global variables or arguments for the rule. For example, the following defines `window` as a global variable for code that should not trigger the rule being tested:
```js
valid: [
{
code: "window.alert()",
globals: [ "window" ]
}
]
```
You can also pass options to the rule (if it accepts them). These arguments are equivalent to how people can configure rules in their `.eslintrc` file. For example:
```js
valid: [
{
code: "var msg = 'Hello';",
options: [ "single" ]
}
]
```
The `options` property must be an array of options. This gets passed through to `context.options` in the rule.
### Invalid Code
Each invalid case must be an object containing the code to test and at least one message that is produced by the rule. The `errors` key specifies an array of objects, each containing a message (your rule may trigger multiple messages for the same code). You should also specify the type of AST node you expect to receive back using the `type` key. The AST node should represent the actual spot in the code where there is a problem. For example:
```js
invalid: [
{
code: "function doSomething() { var f; if (true) { var build = true; } f = build; }",
errors: [
{ message: "build used outside of binding context.", type: "Identifier" }
]
}
]
```
In this case, the message is specific to the variable being used and the AST node type is `Identifier`.
Similar to the valid cases, you can also specify `options` to be passed to the rule:
```js
invalid: [
{
code: "function doSomething() { var f; if (true) { var build = true; } f = build; }",
options: [ "double" ],
errors: [
{ message: "build used outside of binding context.", type: "Identifier" }
]
}
]
```
For simpler cases where the only thing that really matters is the error message, you can also specify any `errors` as strings. You can also have some strings and some objects, if you like.
```js
invalid: [
{
code: "'single quotes'",
options: ["double"],
errors: ["Strings must use doublequote."]
}
]
```
### Specifying Parser Options
Some tests require that a certain parser configuration must be used. This can be specified in test specifications via the `parserOptions` setting.
For example, to set `ecmaVersion` to 6 (in order to use constructs like `for ... of`):
```js
valid: [
{
code: "for (x of a) doSomething();",
parserOptions: { ecmaVersion: 6 }
}
]
```
If you are working with ES6 modules:
```js
valid: [
{
code: "export default function () {};",
parserOptions: { ecmaVersion: 6, sourceType: "module" }
}
]
```
For non-version specific features such as JSX:
```js
valid: [
{
code: "var foo = <div>{bar}</div>",
parserOptions: { ecmaFeatures: { jsx: true } }
}
]
```
The options available and the expected syntax for `parserOptions` is the same as those used in [configuration](../user-guide/configuring.md#specifying-parser-options).
### Write Several Tests
Provide as many unit tests as possible. Your pull request will never be turned down for having too many tests submitted with it!
## Performance Testing
To keep the linting process efficient and unobtrusive, it is useful to verify the performance impact of new rules or modifications to existing rules.
### Overall Performance
The `npm run perf` command gives a high-level overview of ESLint running time with default rules (`eslint:recommended`) enabled.
```bash
$ git checkout master
Switched to branch 'master'
$ npm run perf
CPU Speed is 2200 with multiplier 7500000
Performance Run #1: 1394.689313ms
Performance Run #2: 1423.295351ms
Performance Run #3: 1385.09515ms
Performance Run #4: 1382.406982ms
Performance Run #5: 1409.68566ms
Performance budget ok: 1394.689313ms (limit: 3409.090909090909ms)
$ git checkout my-rule-branch
Switched to branch 'my-rule-branch'
$ npm run perf
CPU Speed is 2200 with multiplier 7500000
Performance Run #1: 1443.736547ms
Performance Run #2: 1419.193291ms
Performance Run #3: 1436.018228ms
Performance Run #4: 1473.605485ms
Performance Run #5: 1457.455283ms
Performance budget ok: 1443.736547ms (limit: 3409.090909090909ms)
```
### Per-rule Performance
ESLint has a built-in method to track performance of individual rules. Setting the `TIMING` environment variable will trigger the display, upon linting completion, of the ten longest-running rules, along with their individual running time and relative performance impact as a percentage of total rule processing time.
```bash
$ TIMING=1 eslint lib
Rule | Time (ms) | Relative
:-----------------------|----------:|--------:
no-multi-spaces | 52.472 | 6.1%
camelcase | 48.684 | 5.7%
no-irregular-whitespace | 43.847 | 5.1%
valid-jsdoc | 40.346 | 4.7%
handle-callback-err | 39.153 | 4.6%
space-infix-ops | 35.444 | 4.1%
no-undefined | 25.693 | 3.0%
no-shadow | 22.759 | 2.7%
no-empty-class | 21.976 | 2.6%
semi | 19.359 | 2.3%
```
To test one rule explicitly, combine the `--no-eslintrc`, and `--rule` options:
```bash
$ TIMING=1 eslint --no-eslintrc --rule "quotes: [2, 'double']" lib
Rule | Time (ms) | Relative
:------|----------:|--------:
quotes | 18.066 | 100.0%
```
## Rule Naming Conventions
The rule naming conventions for ESLint are fairly simple:
* If your rule is disallowing something, prefix it with `no-` such as `no-eval` for disallowing `eval()` and `no-debugger` for disallowing `debugger`.
* If your rule is enforcing the inclusion of something, use a short name without a special prefix.
* Keep your rule names as short as possible, use abbreviations where appropriate, and no more than four words.
* Use dashes between words.
## Rule Acceptance Criteria
Because rules are highly personal (and therefore very contentious), accepted rules should:
* Not be library-specific.
* Demonstrate a possible issue that can be resolved by rewriting the code.
* Be general enough so as to apply for a large number of developers.
* Not be the opposite of an existing rule.
* Not overlap with an existing rule.
## Runtime Rules
The thing that makes ESLint different from other linters is the ability to define custom rules at runtime. This is perfect for rules that are specific to your project or company and wouldn't make sense for ESLint to ship with. With runtime rules, you don't have to wait for the next version of ESLint or be disappointed that your rule isn't general enough to apply to the larger JavaScript community, just write your rules and include them at runtime.
Runtime rules are written in the same format as all other rules. Create your rule as you would any other and then follow these steps:
1. Place all of your runtime rules in the same directory (i.e., `eslint_rules`).
2. Create a [configuration file](../user-guide/configuring.md) and specify your rule ID error level under the `rules` key. Your rule will not run unless it has a value of `1` or `2` in the configuration file.
3. Run the [command line interface](../user-guide/command-line-interface.md) using the `--rulesdir` option to specify the location of your runtime rules.

View File

@ -0,0 +1,737 @@
# Working with Rules
**Note:** This page covers the most recent rule format for ESLint >= 3.0.0. There is also a [deprecated rule format](./working-with-rules-deprecated.md).
Each rule in ESLint has three files named with its identifier (for example, `no-extra-semi`).
* in the `lib/rules` directory: a source file (for example, `no-extra-semi.js`)
* in the `tests/lib/rules` directory: a test file (for example, `no-extra-semi.js`)
* in the `docs/rules` directory: a Markdown documentation file (for example, `no-extra-semi.md`)
**Important:** If you submit a **core** rule to the ESLint repository, you **must** follow some conventions explained below.
Here is the basic format of the source file for a rule:
```js
/**
* @fileoverview Rule to disallow unnecessary semicolons
* @author Nicholas C. Zakas
*/
"use strict";
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: "suggestion",
docs: {
description: "disallow unnecessary semicolons",
category: "Possible Errors",
recommended: true,
url: "https://eslint.org/docs/rules/no-extra-semi"
},
fixable: "code",
schema: [] // no options
},
create: function(context) {
return {
// callback functions
};
}
};
```
## Rule Basics
The source file for a rule exports an object with the following properties.
`meta` (object) contains metadata for the rule:
* `type` (string) indicates the type of rule, which is one of `"problem"`, `"suggestion"`, or `"layout"`:
* `"problem"` means the rule is identifying code that either will cause an error or may cause a confusing behavior. Developers should consider this a high priority to resolve.
* `"suggestion"` means the rule is identifying something that could be done in a better way but no errors will occur if the code isn't changed.
* `"layout"` means the rule cares primarily about whitespace, semicolons, commas, and parentheses, all the parts of the program that determine how the code looks rather than how it executes. These rules work on parts of the code that aren't specified in the AST.
* `docs` (object) is required for core rules of ESLint:
* `description` (string) provides the short description of the rule in the [rules index](../rules/)
* `category` (string) specifies the heading under which the rule is listed in the [rules index](../rules/)
* `recommended` (boolean) is whether the `"extends": "eslint:recommended"` property in a [configuration file](../user-guide/configuring.md#extending-configuration-files) enables the rule
* `url` (string) specifies the URL at which the full documentation can be accessed
* `suggestion` (boolean) specifies whether rules can return suggestions (defaults to false if omitted)
In a custom rule or plugin, you can omit `docs` or include any properties that you need in it.
* `fixable` (string) is either `"code"` or `"whitespace"` if the `--fix` option on the [command line](../user-guide/command-line-interface.md#fix) automatically fixes problems reported by the rule
**Important:** Without the `fixable` property, ESLint does not [apply fixes](#applying-fixes) even if the rule implements `fix` functions. Omit the `fixable` property if the rule is not fixable.
* `schema` (array) specifies the [options](#options-schemas) so ESLint can prevent invalid [rule configurations](../user-guide/configuring.md#configuring-rules)
* `deprecated` (boolean) indicates whether the rule has been deprecated. You may omit the `deprecated` property if the rule has not been deprecated.
* `replacedBy` (array) in the case of a deprecated rule, specifies replacement rule(s)
`create` (function) returns an object with methods that ESLint calls to "visit" nodes while traversing the abstract syntax tree (AST as defined by [ESTree](https://github.com/estree/estree)) of JavaScript code:
* if a key is a node type or a [selector](./selectors.md), ESLint calls that **visitor** function while going **down** the tree
* if a key is a node type or a [selector](./selectors.md) plus `:exit`, ESLint calls that **visitor** function while going **up** the tree
* if a key is an event name, ESLint calls that **handler** function for [code path analysis](./code-path-analysis.md)
A rule can use the current node and its surrounding tree to report or fix problems.
Here are methods for the [array-callback-return](../rules/array-callback-return.md) rule:
```js
function checkLastSegment (node) {
// report problem for function if last code path segment is reachable
}
module.exports = {
meta: { ... },
create: function(context) {
// declare the state of the rule
return {
ReturnStatement: function(node) {
// at a ReturnStatement node while going down
},
// at a function expression node while going up:
"FunctionExpression:exit": checkLastSegment,
"ArrowFunctionExpression:exit": checkLastSegment,
onCodePathStart: function (codePath, node) {
// at the start of analyzing a code path
},
onCodePathEnd: function(codePath, node) {
// at the end of analyzing a code path
}
};
}
};
```
## The Context Object
The `context` object contains additional functionality that is helpful for rules to do their jobs. As the name implies, the `context` object contains information that is relevant to the context of the rule. The `context` object has the following properties:
* `parserOptions` - the parser options configured for this run (more details [here](../user-guide/configuring.md#specifying-parser-options)).
* `id` - the rule ID.
* `options` - an array of the [configured options](/docs/user-guide/configuring.md#configuring-rules) for this rule. This array does not include the rule severity. For more information, see [here](#contextoptions).
* `settings` - the [shared settings](/docs/user-guide/configuring.md#adding-shared-settings) from configuration.
* `parserPath` - the name of the `parser` from configuration.
* `parserServices` - an object containing parser-provided services for rules. The default parser does not provide any services. However, if a rule is intended to be used with a custom parser, it could use `parserServices` to access anything provided by that parser. (For example, a TypeScript parser could provide the ability to get the computed type of a given node.)
Additionally, the `context` object has the following methods:
* `getAncestors()` - returns an array of the ancestors of the currently-traversed node, starting at the root of the AST and continuing through the direct parent of the current node. This array does not include the currently-traversed node itself.
* `getCwd()` - returns the `cwd` passed to [Linter](./nodejs-api.md#Linter). It is a path to a directory that should be considered as the current working directory.
* `getDeclaredVariables(node)` - returns a list of [variables](./scope-manager-interface.md#variable-interface) declared by the given node. This information can be used to track references to variables.
* If the node is a `VariableDeclaration`, all variables declared in the declaration are returned.
* If the node is a `VariableDeclarator`, all variables declared in the declarator are returned.
* If the node is a `FunctionDeclaration` or `FunctionExpression`, the variable for the function name is returned, in addition to variables for the function parameters.
* If the node is an `ArrowFunctionExpression`, variables for the parameters are returned.
* If the node is a `ClassDeclaration` or a `ClassExpression`, the variable for the class name is returned.
* If the node is a `CatchClause`, the variable for the exception is returned.
* If the node is an `ImportDeclaration`, variables for all of its specifiers are returned.
* If the node is an `ImportSpecifier`, `ImportDefaultSpecifier`, or `ImportNamespaceSpecifier`, the declared variable is returned.
* Otherwise, if the node does not declare any variables, an empty array is returned.
* `getFilename()` - returns the filename associated with the source.
* `getScope()` - returns the [scope](./scope-manager-interface.md#scope-interface) of the currently-traversed node. This information can be used to track references to variables.
* `getSourceCode()` - returns a [`SourceCode`](#contextgetsourcecode) object that you can use to work with the source that was passed to ESLint.
* `markVariableAsUsed(name)` - marks a variable with the given name in the current scope as used. This affects the [no-unused-vars](../rules/no-unused-vars.md) rule. Returns `true` if a variable with the given name was found and marked as used, otherwise `false`.
* `report(descriptor)` - reports a problem in the code (see the [dedicated section](#context-report)).
**Note:** Earlier versions of ESLint supported additional methods on the `context` object. Those methods were removed in the new format and should not be relied upon.
### context.getScope()
This method returns the scope which has the following types:
| AST Node Type | Scope Type |
|:--------------------------|:-----------|
| `Program` | `global` |
| `FunctionDeclaration` | `function` |
| `FunctionExpression` | `function` |
| `ArrowFunctionExpression` | `function` |
| `ClassDeclaration` | `class` |
| `ClassExpression` | `class` |
| `BlockStatement` ※1 | `block` |
| `SwitchStatement` ※1 | `switch` |
| `ForStatement` ※2 | `for` |
| `ForInStatement` ※2 | `for` |
| `ForOfStatement` ※2 | `for` |
| `WithStatement` | `with` |
| `CatchClause` | `catch` |
| others | ※3 |
**※1** Only if the configured parser provided the block-scope feature. The default parser provides the block-scope feature if `parserOptions.ecmaVersion` is not less than `6`.<br>
**※2** Only if the `for` statement defines the iteration variable as a block-scoped variable (E.g., `for (let i = 0;;) {}`).<br>
**※3** The scope of the closest ancestor node which has own scope. If the closest ancestor node has multiple scopes then it chooses the innermost scope (E.g., the `Program` node has a `global` scope and a `module` scope if `Program#sourceType` is `"module"`. The innermost scope is the `module` scope.).
The returned value is a [`Scope` object](scope-manager-interface.md) defined by the `eslint-scope` package. The `Variable` objects of global variables have some additional properties.
* `variable.writeable` (`boolean | undefined`) ... If `true`, this global variable can be assigned arbitrary value. If `false`, this global variable is read-only.
* `variable.eslintExplicitGlobal` (`boolean | undefined`) ... If `true`, this global variable was defined by a `/* globals */` directive comment in the source code file.
* `variable.eslintExplicitGlobalComments` (`Comment[] | undefined`) ... The array of `/* globals */` directive comments which defined this global variable in the source code file. This property is `undefined` if there are no `/* globals */` directive comments.
* `variable.eslintImplicitGlobalSetting` (`"readonly" | "writable" | undefined`) ... The configured value in config files. This can be different from `variable.writeable` if there are `/* globals */` directive comments.
### context.report()
The main method you'll use is `context.report()`, which publishes a warning or error (depending on the configuration being used). This method accepts a single argument, which is an object containing the following properties:
* `message` - the problem message.
* `node` - (optional) the AST node related to the problem. If present and `loc` is not specified, then the starting location of the node is used as the location of the problem.
* `loc` - (optional) an object specifying the location of the problem. If both `loc` and `node` are specified, then the location is used from `loc` instead of `node`.
* `start` - An object of the start location.
* `line` - the 1-based line number at which the problem occurred.
* `column` - the 0-based column number at which the problem occurred.
* `end` - An object of the end location.
* `line` - the 1-based line number at which the problem occurred.
* `column` - the 0-based column number at which the problem occurred.
* `data` - (optional) [placeholder](#using-message-placeholders) data for `message`.
* `fix` - (optional) a function that applies a [fix](#applying-fixes) to resolve the problem.
Note that at least one of `node` or `loc` is required.
The simplest example is to use just `node` and `message`:
```js
context.report({
node: node,
message: "Unexpected identifier"
});
```
The node contains all of the information necessary to figure out the line and column number of the offending text as well the source text representing the node.
### Using message placeholders
You can also use placeholders in the message and provide `data`:
```js
{% raw %}
context.report({
node: node,
message: "Unexpected identifier: {{ identifier }}",
data: {
identifier: node.name
}
});
{% endraw %}
```
Note that leading and trailing whitespace is optional in message parameters.
The node contains all of the information necessary to figure out the line and column number of the offending text as well the source text representing the node.
### `messageId`s
Instead of typing out messages in both the `context.report()` call and your tests, you can use `messageId`s instead.
This allows you to avoid retyping error messages. It also prevents errors reported in different sections of your rule from having out-of-date messages.
```js
{% raw %}
// in your rule
module.exports = {
meta: {
messages: {
avoidName: "Avoid using variables named '{{ name }}'"
}
},
create(context) {
return {
Identifier(node) {
if (node.name === "foo") {
context.report({
node,
messageId: "avoidName",
data: {
name: "foo",
}
});
}
}
};
}
};
// in the file to lint:
var foo = 2;
// ^ error: Avoid using variables named 'foo'
// In your tests:
var rule = require("../../../lib/rules/my-rule");
var RuleTester = require("eslint").RuleTester;
var ruleTester = new RuleTester();
ruleTester.run("my-rule", rule, {
valid: ["bar", "baz"],
invalid: [
{
code: "foo",
errors: [
{
messageId: "avoidName"
}
]
}
]
});
{% endraw %}
```
### Applying Fixes
If you'd like ESLint to attempt to fix the problem you're reporting, you can do so by specifying the `fix` function when using `context.report()`. The `fix` function receives a single argument, a `fixer` object, that you can use to apply a fix. For example:
```js
context.report({
node: node,
message: "Missing semicolon",
fix: function(fixer) {
return fixer.insertTextAfter(node, ";");
}
});
```
Here, the `fix()` function is used to insert a semicolon after the node. Note that a fix is not immediately applied, and may not be applied at all if there are conflicts with other fixes. After applying fixes, ESLint will run all of the enabled rules again on the fixed code, potentially applying more fixes. This process will repeat up to 10 times, or until no more fixable problems are found. Afterwards, any remaining problems will be reported as usual.
**Important:** Unless the rule [exports](#rule-basics) the `meta.fixable` property, ESLint does not apply fixes even if the rule implements `fix` functions.
The `fixer` object has the following methods:
* `insertTextAfter(nodeOrToken, text)` - inserts text after the given node or token
* `insertTextAfterRange(range, text)` - inserts text after the given range
* `insertTextBefore(nodeOrToken, text)` - inserts text before the given node or token
* `insertTextBeforeRange(range, text)` - inserts text before the given range
* `remove(nodeOrToken)` - removes the given node or token
* `removeRange(range)` - removes text in the given range
* `replaceText(nodeOrToken, text)` - replaces the text in the given node or token
* `replaceTextRange(range, text)` - replaces the text in the given range
The above methods return a `fixing` object.
The `fix()` function can return the following values:
* A `fixing` object.
* An array which includes `fixing` objects.
* An iterable object which enumerates `fixing` objects. Especially, the `fix()` function can be a generator.
If you make a `fix()` function which returns multiple `fixing` objects, those `fixing` objects must not be overlapped.
Best practices for fixes:
1. Avoid any fixes that could change the runtime behavior of code and cause it to stop working.
1. Make fixes as small as possible. Fixes that are unnecessarily large could conflict with other fixes, and prevent them from being applied.
1. Only make one fix per message. This is enforced because you must return the result of the fixer operation from `fix()`.
1. Since all rules are run again after the initial round of fixes is applied, it's not necessary for a rule to check whether the code style of a fix will cause errors to be reported by another rule.
* For example, suppose a fixer would like to surround an object key with quotes, but it's not sure whether the user would prefer single or double quotes.
```js
({ foo : 1 })
// should get fixed to either
({ 'foo': 1 })
// or
({ "foo": 1 })
```
* This fixer can just select a quote type arbitrarily. If it guesses wrong, the resulting code will be automatically reported and fixed by the [`quotes`](/docs/rules/quotes.md) rule.
### Providing Suggestions
In some cases fixes aren't appropriate to be automatically applied, for example, if a fix potentially changes functionality or if there are multiple valid ways to fix a rule depending on the implementation intent (see the best practices for [applying fixes](#applying-fixes) listed above). In these cases, there is an alternative `suggest` option on `context.report()` that allows other tools, such as editors, to expose helpers for users to manually apply a suggestion.
In order to provide suggestions, use the `suggest` key in the report argument with an array of suggestion objects. The suggestion objects represent individual suggestions that could be applied and require either a `desc` key string that describes what applying the suggestion would do or a `messageId` key (see [below](#suggestion-messageids)), and a `fix` key that is a function defining the suggestion result. This `fix` function follows the same API as regular fixes (described above in [applying fixes](#applying-fixes)).
```js
{% raw %}
context.report({
node: node,
message: "Unnecessary escape character: \\{{character}}.",
data: { character },
suggest: [
{
desc: "Remove the `\\`. This maintains the current functionality.",
fix: function(fixer) {
return fixer.removeRange(range);
}
},
{
desc: "Replace the `\\` with `\\\\` to include the actual backslash character.",
fix: function(fixer) {
return fixer.insertTextBeforeRange(range, "\\");
}
}
]
});
{% endraw %}
```
Note: Suggestions will be applied as a stand-alone change, without triggering multipass fixes. Each suggestion should focus on a singular change in the code and should not try to conform to user defined styles. For example, if a suggestion is adding a new statement into the codebase, it should not try to match correct indentation, or confirm to user preferences on presence/absence of semicolumns. All of those things can be corrected by multipass autofix when the user triggers it.
Best practices for suggestions:
1. Don't try to do too much and suggest large refactors that could introduce a lot of breaking changes.
1. As noted above, don't try to conform to user-defined styles.
#### Suggestion `messageId`s
Instead of using a `desc` key for suggestions a `messageId` can be used instead. This works the same way as `messageId`s for the overall error (see [messageIds](#messageIds)). Here is an example of how to use it in a rule:
```js
{% raw %}
module.exports = {
meta: {
messages: {
unnecessaryEscape: "Unnecessary escape character: \\{{character}}.",
removeEscape: "Remove the `\\`. This maintains the current functionality.",
escapeBackslash: "Replace the `\\` with `\\\\` to include the actual backslash character."
}
},
create: function(context) {
// ...
context.report({
node: node,
messageId: 'unnecessaryEscape',
data: { character },
suggest: [
{
messageId: "removeEscape",
fix: function(fixer) {
return fixer.removeRange(range);
}
},
{
messageId: "escapeBackslash",
fix: function(fixer) {
return fixer.insertTextBeforeRange(range, "\\");
}
}
]
});
}
};
{% endraw %}
```
#### Placeholders in suggestion messages
You can also use placeholders in the suggestion message. This works the same way as placeholders for the overall error (see [using message placeholders](#using-message-placeholders)).
Please note that you have to provide `data` on the suggestion's object. Suggestion messages cannot use properties from the overall error's `data`.
```js
{% raw %}
module.exports = {
meta: {
messages: {
unnecessaryEscape: "Unnecessary escape character: \\{{character}}.",
removeEscape: "Remove `\\` before {{character}}.",
}
},
create: function(context) {
// ...
context.report({
node: node,
messageId: "unnecessaryEscape",
data: { character }, // data for the unnecessaryEscape overall message
suggest: [
{
messageId: "removeEscape",
data: { character }, // data for the removeEscape suggestion message
fix: function(fixer) {
return fixer.removeRange(range);
}
}
]
});
}
};
{% endraw %}
```
### context.options
Some rules require options in order to function correctly. These options appear in configuration (`.eslintrc`, command line, or in comments). For example:
```json
{
"quotes": ["error", "double"]
}
```
The `quotes` rule in this example has one option, `"double"` (the `error` is the error level). You can retrieve the options for a rule by using `context.options`, which is an array containing every configured option for the rule. In this case, `context.options[0]` would contain `"double"`:
```js
module.exports = {
create: function(context) {
var isDouble = (context.options[0] === "double");
// ...
}
};
```
Since `context.options` is just an array, you can use it to determine how many options have been passed as well as retrieving the actual options themselves. Keep in mind that the error level is not part of `context.options`, as the error level cannot be known or modified from inside a rule.
When using options, make sure that your rule has some logical defaults in case the options are not provided.
### context.getSourceCode()
The `SourceCode` object is the main object for getting more information about the source code being linted. You can retrieve the `SourceCode` object at any time by using the `getSourceCode()` method:
```js
module.exports = {
create: function(context) {
var sourceCode = context.getSourceCode();
// ...
}
};
```
Once you have an instance of `SourceCode`, you can use the methods on it to work with the code:
* `getText(node)` - returns the source code for the given node. Omit `node` to get the whole source.
* `getAllComments()` - returns an array of all comments in the source.
* `getCommentsBefore(nodeOrToken)` - returns an array of comment tokens that occur directly before the given node or token.
* `getCommentsAfter(nodeOrToken)` - returns an array of comment tokens that occur directly after the given node or token.
* `getCommentsInside(node)` - returns an array of all comment tokens inside a given node.
* `getJSDocComment(node)` - returns the JSDoc comment for a given node or `null` if there is none.
* `isSpaceBetween(nodeOrToken, nodeOrToken)` - returns true if there is a whitespace character between the two tokens or, if given a node, the last token of the first node and the first token of the second node.
* `getFirstToken(node, skipOptions)` - returns the first token representing the given node.
* `getFirstTokens(node, countOptions)` - returns the first `count` tokens representing the given node.
* `getLastToken(node, skipOptions)` - returns the last token representing the given node.
* `getLastTokens(node, countOptions)` - returns the last `count` tokens representing the given node.
* `getTokenAfter(nodeOrToken, skipOptions)` - returns the first token after the given node or token.
* `getTokensAfter(nodeOrToken, countOptions)` - returns `count` tokens after the given node or token.
* `getTokenBefore(nodeOrToken, skipOptions)` - returns the first token before the given node or token.
* `getTokensBefore(nodeOrToken, countOptions)` - returns `count` tokens before the given node or token.
* `getFirstTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions)` - returns the first token between two nodes or tokens.
* `getFirstTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)` - returns the first `count` tokens between two nodes or tokens.
* `getLastTokenBetween(nodeOrToken1, nodeOrToken2, skipOptions)` - returns the last token between two nodes or tokens.
* `getLastTokensBetween(nodeOrToken1, nodeOrToken2, countOptions)` - returns the last `count` tokens between two nodes or tokens.
* `getTokens(node)` - returns all tokens for the given node.
* `getTokensBetween(nodeOrToken1, nodeOrToken2)` - returns all tokens between two nodes.
* `getTokenByRangeStart(index, rangeOptions)` - returns the token whose range starts at the given index in the source.
* `getNodeByRangeIndex(index)` - returns the deepest node in the AST containing the given source index.
* `getLocFromIndex(index)` - returns an object with `line` and `column` properties, corresponding to the location of the given source index. `line` is 1-based and `column` is 0-based.
* `getIndexFromLoc(loc)` - returns the index of a given location in the source code, where `loc` is an object with a 1-based `line` key and a 0-based `column` key.
* `commentsExistBetween(nodeOrToken1, nodeOrToken2)` - returns `true` if comments exist between two nodes.
`skipOptions` is an object which has 3 properties; `skip`, `includeComments`, and `filter`. Default is `{skip: 0, includeComments: false, filter: null}`.
* `skip` is a positive integer, the number of skipping tokens. If `filter` option is given at the same time, it doesn't count filtered tokens as skipped.
* `includeComments` is a boolean value, the flag to include comment tokens into the result.
* `filter` is a function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
`countOptions` is an object which has 3 properties; `count`, `includeComments`, and `filter`. Default is `{count: 0, includeComments: false, filter: null}`.
* `count` is a positive integer, the maximum number of returning tokens.
* `includeComments` is a boolean value, the flag to include comment tokens into the result.
* `filter` is a function which gets a token as the first argument, if the function returns `false` then the result excludes the token.
`rangeOptions` is an object which has 1 property: `includeComments`.
* `includeComments` is a boolean value, the flag to include comment tokens into the result.
There are also some properties you can access:
* `hasBOM` - the flag to indicate whether or not the source code has Unicode BOM.
* `text` - the full text of the code being linted. Unicode BOM has been stripped from this text.
* `ast` - the `Program` node of the AST for the code being linted.
* `scopeManager` - the [ScopeManager](./scope-manager-interface.md#scopemanager-interface) object of the code.
* `visitorKeys` - the visitor keys to traverse this AST.
* `lines` - an array of lines, split according to the specification's definition of line breaks.
You should use a `SourceCode` object whenever you need to get more information about the code being linted.
#### Deprecated
Please note that the following methods have been deprecated and will be removed in a future version of ESLint:
* `getComments()` - replaced by `getCommentsBefore()`, `getCommentsAfter()`, and `getCommentsInside()`
* `getTokenOrCommentBefore()` - replaced by `getTokenBefore()` with the `{ includeComments: true }` option
* `getTokenOrCommentAfter()` - replaced by `getTokenAfter()` with the `{ includeComments: true }` option
* `isSpaceBetweenTokens()` - replaced by `isSpaceBetween()`
### Options Schemas
Rules may export a `schema` property, which is a [JSON schema](http://json-schema.org/) format description of a rule's options which will be used by ESLint to validate configuration options and prevent invalid or unexpected inputs before they are passed to the rule in `context.options`.
There are two formats for a rule's exported `schema`. The first is a full JSON Schema object describing all possible options the rule accepts, including the rule's error level as the first argument and any optional arguments thereafter.
However, to simplify schema creation, rules may also export an array of schemas for each optional positional argument, and ESLint will automatically validate the required error level first. For example, the `yoda` rule accepts a primary mode argument, as well as an extra options object with named properties.
```js
// "yoda": [2, "never", { "exceptRange": true }]
module.exports = {
meta: {
schema: [
{
"enum": ["always", "never"]
},
{
"type": "object",
"properties": {
"exceptRange": {
"type": "boolean"
}
},
"additionalProperties": false
}
]
},
};
```
In the preceding example, the error level is assumed to be the first argument. It is followed by the first optional argument, a string which may be either `"always"` or `"never"`. The final optional argument is an object, which may have a Boolean property named `exceptRange`.
To learn more about JSON Schema, we recommend looking at some examples in [website](http://json-schema.org/learn/) to start, and also reading [Understanding JSON Schema](http://spacetelescope.github.io/understanding-json-schema/) (a free ebook).
**Note:** Currently you need to use full JSON Schema object rather than array in case your schema has references ($ref), because in case of array format ESLint transforms this array into a single schema without updating references that makes them incorrect (they are ignored).
### Getting the Source
If your rule needs to get the actual JavaScript source to work with, then use the `sourceCode.getText()` method. This method works as follows:
```js
// get all source
var source = sourceCode.getText();
// get source for just this AST node
var nodeSource = sourceCode.getText(node);
// get source for AST node plus previous two characters
var nodeSourceWithPrev = sourceCode.getText(node, 2);
// get source for AST node plus following two characters
var nodeSourceWithFollowing = sourceCode.getText(node, 0, 2);
```
In this way, you can look for patterns in the JavaScript text itself when the AST isn't providing the appropriate data (such as location of commas, semicolons, parentheses, etc.).
### Accessing Comments
While comments are not technically part of the AST, ESLint provides a few ways for rules to access them:
#### sourceCode.getAllComments()
This method returns an array of all the comments found in the program. This is useful for rules that need to check all comments regardless of location.
#### sourceCode.getCommentsBefore(), sourceCode.getCommentsAfter(), and sourceCode.getCommentsInside()
These methods return an array of comments that appear directly before, directly after, and inside nodes, respectively. They are useful for rules that need to check comments in relation to a given node or token.
Keep in mind that the results of this method are calculated on demand.
#### Token traversal methods
Finally, comments can be accessed through many of `sourceCode`'s methods using the `includeComments` option.
### Accessing Shebangs
Shebangs are represented by tokens of type `"Shebang"`. They are treated as comments and can be accessed by the methods outlined above.
### Accessing Code Paths
ESLint analyzes code paths while traversing AST.
You can access that code path objects with five events related to code paths.
[details here](./code-path-analysis.md)
## Rule Unit Tests
Each bundled rule for ESLint core must have a set of unit tests submitted with it to be accepted. The test file is named the same as the source file but lives in `tests/lib/`. For example, if the rule source file is `lib/rules/foo.js` then the test file should be `tests/lib/rules/foo.js`.
ESLint provides the [`RuleTester`](/docs/developer-guide/nodejs-api.md#ruletester) utility to make it easy to write tests for rules.
## Performance Testing
To keep the linting process efficient and unobtrusive, it is useful to verify the performance impact of new rules or modifications to existing rules.
### Overall Performance
When developing in the ESLint core repository, the `npm run perf` command gives a high-level overview of ESLint running time with all core rules enabled.
```bash
$ git checkout master
Switched to branch 'master'
$ npm run perf
CPU Speed is 2200 with multiplier 7500000
Performance Run #1: 1394.689313ms
Performance Run #2: 1423.295351ms
Performance Run #3: 1385.09515ms
Performance Run #4: 1382.406982ms
Performance Run #5: 1409.68566ms
Performance budget ok: 1394.689313ms (limit: 3409.090909090909ms)
$ git checkout my-rule-branch
Switched to branch 'my-rule-branch'
$ npm run perf
CPU Speed is 2200 with multiplier 7500000
Performance Run #1: 1443.736547ms
Performance Run #2: 1419.193291ms
Performance Run #3: 1436.018228ms
Performance Run #4: 1473.605485ms
Performance Run #5: 1457.455283ms
Performance budget ok: 1443.736547ms (limit: 3409.090909090909ms)
```
### Per-rule Performance
ESLint has a built-in method to track performance of individual rules. Setting the `TIMING` environment variable will trigger the display, upon linting completion, of the ten longest-running rules, along with their individual running time and relative performance impact as a percentage of total rule processing time.
```bash
$ TIMING=1 eslint lib
Rule | Time (ms) | Relative
:-----------------------|----------:|--------:
no-multi-spaces | 52.472 | 6.1%
camelcase | 48.684 | 5.7%
no-irregular-whitespace | 43.847 | 5.1%
valid-jsdoc | 40.346 | 4.7%
handle-callback-err | 39.153 | 4.6%
space-infix-ops | 35.444 | 4.1%
no-undefined | 25.693 | 3.0%
no-shadow | 22.759 | 2.7%
no-empty-class | 21.976 | 2.6%
semi | 19.359 | 2.3%
```
To test one rule explicitly, combine the `--no-eslintrc`, and `--rule` options:
```bash
$ TIMING=1 eslint --no-eslintrc --rule "quotes: [2, 'double']" lib
Rule | Time (ms) | Relative
:------|----------:|--------:
quotes | 18.066 | 100.0%
```
## Rule Naming Conventions
The rule naming conventions for ESLint are fairly simple:
* If your rule is disallowing something, prefix it with `no-` such as `no-eval` for disallowing `eval()` and `no-debugger` for disallowing `debugger`.
* If your rule is enforcing the inclusion of something, use a short name without a special prefix.
* Use dashes between words.
## Runtime Rules
The thing that makes ESLint different from other linters is the ability to define custom rules at runtime. This is perfect for rules that are specific to your project or company and wouldn't make sense for ESLint to ship with. With runtime rules, you don't have to wait for the next version of ESLint or be disappointed that your rule isn't general enough to apply to the larger JavaScript community, just write your rules and include them at runtime.
Runtime rules are written in the same format as all other rules. Create your rule as you would any other and then follow these steps:
1. Place all of your runtime rules in the same directory (e.g., `eslint_rules`).
2. Create a [configuration file](../user-guide/configuring.md) and specify your rule ID error level under the `rules` key. Your rule will not run unless it has a value of `1` or `2` in the configuration file.
3. Run the [command line interface](../user-guide/command-line-interface.md) using the `--rulesdir` option to specify the location of your runtime rules.

View File

@ -0,0 +1,23 @@
# Maintainer Guide
This guide is intended for those who work as part of the ESLint project team.
## [Managing Issues](issues.md)
Describes how to deal with issues when they're opened, when interacting with users, and how to close them effectively.
## [Reviewing Pull Requests](pullrequests.md)
Describes how to review incoming pull requests.
## [Managing Releases](releases.md)
Describes how to do an ESLint project release.
## [Governance](governance.md)
Describes the governance policy for ESLint, including the rights and privileges of individuals inside the project.
## [Working Groups](working-groups.md)
Describes how working groups are created and how they function within the ESLint project.

View File

@ -0,0 +1,174 @@
# Governance
ESLint is an open source project that depends on contributions from the community. Anyone may contribute to the project at any time by submitting code, participating in discussions, making suggestions, or any other contribution they see fit. This document describes how various types of contributors work within the ESLint project.
## Roles and Responsibilities
### Users
Users are community members who have a need for the project. Anyone can be a User; there are no special requirements. Common User contributions include evangelizing the project (e.g., display a link on a website and raise awareness through word-of-mouth), informing developers of strengths and weaknesses from a new user perspective, or providing moral support (a "thank you" goes a long way).
Users who continue to engage with the project and its community will often become more and more involved. Such Users may find themselves becoming Contributors, as described in the next section.
### Contributors
Contributors are community members who contribute in concrete ways to the project, most often in the form of code and/or documentation. Anyone can become a Contributor, and contributions can take many forms. There is no expectation of commitment to the project, no specific skill requirements, and no selection process.
Contributors have read-only access to source code and so submit changes via pull requests. Contributor pull requests have their contribution reviewed and merged by a TSC member. TSC members and Committers work with Contributors to review their code and prepare it for merging.
As Contributors gain experience and familiarity with the project, their profile within, and commitment to, the community will increase. At some stage, they may find themselves being nominated for committership by an existing Committer.
### Committers
Committers are community members who have shown that they are committed to the continued development of the project through ongoing engagement with the community. Committers are given push access to the project's GitHub repos and must abide by the project's [Contribution Guidelines](contributing).
Committers:
* Are expected to work on public branches of the source repository and submit pull requests from that branch to the master branch.
* Are expected to delete their public branches when they are no longer necessary.
* Must submit pull requests for all changes.
* Have their work reviewed by TSC members before acceptance into the repository.
* May label and close issues (see [Managing Issues](issues.html))
* May merge some pull requests (see [Managing Pull Requests](pullrequests.html))
To become a Committer:
* One must have shown a willingness and ability to participate in the project as a team player. Typically, a potential Committer will need to show that they have an understanding of and alignment with the project, its objectives, and its strategy.
* Committers are expected to be respectful of every community member and to work collaboratively in the spirit of inclusion.
* Have submitted a minimum of 10 qualifying pull requests. What's a qualifying pull request? One that carries significant technical weight and requires little effort to accept because it's well documented and tested.
New Committers can be nominated by any existing Committer. Once they have been nominated, there will be a vote by the TSC members.
It is important to recognize that committership is a privilege, not a right. That privilege must be earned and once earned it can be removed by the TSC members by a standard TSC motion. However, under normal circumstances committership exists for as long as the Committer wishes to continue engaging with the project.
A Committer who shows an above-average level of contribution to the project, particularly with respect to its strategic direction and long-term health, may be nominated to become a reviewer, described below.
#### Process for Adding Committers
1. Send email congratulating the new committer and confirming that they would like to accept. This should also outline the responsibilities of a committer with a link to the maintainer guide.
1. Add the GitHub user to the "ESLint Team" team
1. Add committer email to the ESLint team mailing list
1. Invite to Gitter team chatroom
1. Tweet congratulations to the new committer from the ESLint Twitter account
### Reviewers
Reviewers are community members who have contributed a significant amount of time to the project through triaging of issues, fixing bugs, implementing enhancements/features, and are trusted community leaders.
Reviewers may perform all of the duties of Committers, and also:
* May merge external pull requests for accepted issues upon reviewing and approving the changes.
* May merge their own pull requests once they have collected the feedback they deem necessary. (No pull request should be merged without at least one Committer/Reviewer/TSC member comment stating they've looked at the code.)
To become a Reviewer:
* Work in a helpful and collaborative way with the community.
* Have given good feedback on others' submissions and displayed an overall understanding of the code quality standards for the project.
* Commit to being a part of the community for the long-term.
* Have submitted a minimum of 50 qualifying pull requests.
A Committer is invited to become a Reviewer by existing Reviewers and TSC members. A nomination will result in discussion and then a decision by the TSC.
#### Process for Adding Reviewers
1. Add the GitHub user to the "ESLint Reviewers" GitHub team
1. Tweet congratulations to the new Reviewer from the ESLint Twitter account
### Technical Steering Committee (TSC)
The ESLint project is jointly governed by a Technical Steering Committee (TSC) which is responsible for high-level guidance of the project.
The TSC has final authority over this project including:
* Technical direction
* Project governance and process (including this policy)
* Contribution policy
* GitHub repository hosting
TSC seats are not time-limited. The size of the TSC can not be larger than five members. This size ensures adequate coverage of important areas of expertise balanced with the ability to make decisions efficiently.
The TSC may add additional members to the TSC by a standard TSC motion.
A TSC member may be removed from the TSC by voluntary resignation, by a standard TSC motion, or by missing four consecutive TSC meetings. In all cases, the TSC member will revert to Reviewer status unless they prefer Alumni status.
Changes to TSC membership should be posted in the agenda, and may be suggested as any other agenda item (see "TSC Meetings" below).
No more than 1/3 of the TSC members may be affiliated with the same employer. If removal or resignation of a TSC member, or a change of employment by a TSC member, creates a situation where more than 1/3 of the TSC membership shares an employer, then the situation must be immediately remedied by the resignation or removal of one or more TSC members affiliated with the over-represented employer(s).
TSC members have additional responsibilities over and above those of a Reviewer. These responsibilities ensure the smooth running of the project. TSC members are expected to review code contributions, approve changes to this document, manage the copyrights within the project outputs, and attend regular TSC meetings.
TSC members may perform all of the duties of Reviewers, and also:
* May release new versions of all ESLint projects.
* May participate in TSC meetings.
* May propose budget items.
* May propose new ESLint projects.
There is no specific set of requirements or qualifications for TSC members beyond those that are expected of Reviewers.
A Reviewer is invited to become a TSC member by existing TSC members. A nomination will result in discussion and then a decision by the TSC.
#### Process for Adding TSC Members
1. Add the GitHub user to the "ESLint TSC" GitHub team
1. Set the GitHub user to be have the "Owner" role for the ESLint organization
1. Send a welcome email with a link to the [maintainer guide](./) and the [npm 2FA guide](./npm-2fa).
1. Invite to the Gitter TSC chatroom
1. Make the TSC member an admin on the ESLint team mailing list
1. Add the TSC member to the recurring TSC meeting event on Google Calendar
1. Add the TSC member as an admin to ESLint Twitter Account on Tweetdeck
1. Add the TSC member to the ESLint TSC mailing list as an "Owner"
1. Tweet congratulations to the new TSC member from the ESLint Twitter account
#### TSC Meetings
The TSC meets every other week in the [TSC Meeting](https://gitter.im/eslint/tsc-meetings) chatroom. The meeting is run by
a designated moderator approved by the TSC.
Items are added to the TSC agenda which are considered contentious or
are modifications of governance, contribution policy, TSC membership,
or release process.
The intention of the agenda is not to approve or review all patches.
That should happen continuously on GitHub and be handled by the larger
group of Committers.
Any community member, Committer, or Reviewer can ask that something be added to
the next meeting's agenda by logging a GitHub Issue. Anyone can add the item to the agenda by adding
the "tsc agenda" tag to the issue.
Prior to each TSC meeting, the moderator will share the Agenda with
members of the TSC. TSC members can add any items they like to the
agenda at the beginning of each meeting. The moderator and the TSC
cannot veto or remove items.
No binding votes on TSC agenda items can take place without a quorum of
TSC members present in the meeting. Quorum is achieved when more than
half of the TSC members (minus non-attending members) are present.
The TSC may invite persons or representatives from certain projects to
participate in a non-voting capacity.
The moderator is responsible for summarizing the discussion of each
agenda item and sending it as a pull request after the meeting.
## Consensus Seeking Process
The TSC follows a
[Consensus Seeking](https://en.wikipedia.org/wiki/Consensus-seeking_decision-making)
decision making model.
When an agenda item has appeared to reach a consensus, the moderator
will ask "Does anyone object?" as a final call for dissent from the
consensus.
If an agenda item cannot reach a consensus, a TSC member can call for
either a closing vote or a vote to table the issue to the next
meeting. The call for a vote must be approved by a majority of the TSC
or else the discussion will continue. Simple majority wins.
----
This work is a derivative of [YUI Contributor Model](https://github.com/yui/yui3/wiki/Contributor-Model) and the [Node.js Project Governance Model](https://github.com/nodejs/node/blob/master/GOVERNANCE.md).
This work is licensed under a [Creative Commons Attribution-ShareAlike 2.0 UK: England & Wales License](https://creativecommons.org/licenses/by-sa/2.0/uk/).

View File

@ -0,0 +1,121 @@
# Managing Issues
New issues are filed frequently, and how we respond to those issues directly affects the success of the project. Being part of the project team means helping to triage and address issues as they come in so the project can continue to run smoothly.
## Things to Keep in Mind
1. **Be nice.** Even if the people are being rude or aggressive on an issue, as a project team member you must be the mature one in the conversation. Do your best to work with everyone no matter their style. Remember, poor wording choice can also be a sign of someone who doesn't know English very well, so be sure to consider that when trying to determine the tone of someone's message. Being rude, even when someone is being rude to you, reflects poorly on the team and the project as a whole.
1. **Be inquisitive.** Ask questions on the issue whenever something isn't clear. Don't assume you understand what's being reported if there are details missing. Whenever you are unsure, it's best to ask for more information.
1. **Not all requests are equal.** It's unlikely we'll be able to accommodate every request, so don't be afraid to say that something doesn't fit into the scope of the project or isn't practical. It's better to give such feedback if that's the case.
1. **Close when appropriate.** Don't be afraid to close issues that you don't think will be done, or when it's become clear from the conversation that there's no further work to do. Issues can always be reopened if they are closed incorrectly, so feel free to close issues when appropriate. Just be sure to leave a comment explaining why the issue is being closed (if not closed by a commit).
## Types of Issues
There are four primary issue categories:
1. **Bug** - something isn't working the way it's expected to work.
1. **Enhancement** - a change to something that already exists. For instance, adding a new option to an existing rule or a bug in a rule where fixing it will result in the rule reporting more problems (in this case, use both "Bug" and "Enhancement").
1. **Feature** - adding something that doesn't already exist. For example, adding a new rule, new formatter, or new command line flag.
1. **Question** - an inquiry about how something works that won't result in a code change. We'd prefer if people use the mailing list or chatroom for questions, but sometimes they'll open an issue.
The first goal when evaluating an issue is to determine which category the issue falls into.
## When an Issue is Opened
When an issue is opened, the bot will automatically apply the "triage" label. Issues labeled with "triage" are the ones that need to be looked at by team members to determine what to do next.
The steps for triaging an issue are:
1. Is it clear what is being requested?
* No: add the "needs info" label to the issue. The bot will add a comment asking for more information. You don't need to comment any further until the person who opened the issue responds with the information requested from the bot.
* Yes:
* Remove the "triage" label
* Label questions with the "question" label
* Label bug reports with the "bug" label (also use the "accepted" label if you can reproduce and verify the bug, otherwise add the "evaluating" label to indicate someone needs to verify)
* Label requests for changes to existing features (new rule options, new configuration options, etc.) with the "enhancement" and "evaluating" labels
* Label requests for completely new features (new rules, supporting a new file format, etc.) with the "feature" and "evaluating" labels
* Use an appropriate label for the part of the project the issue refers to:
* "build" - related to commands run during a build (testing, linting, release scripts, etc.)
* "cli" - related to command line input or output, or to `CLIEngine`
* "core" - related to internal APIs
* "documentation" - related to content on eslint.org
* "infrastructure" - related to resources needed for builds or deployment (VMs, CI tools, bots, etc.)
1. Once it's clear what type of issue it is, make sure all of the relevant information is provided:
* **Bugs**: See [bug reporting guidelines](/docs/developer-guide/contributing/reporting-bugs.md)
* **New Rules:** See [rule proposal guidelines](/docs/developer-guide/contributing/new-rules.md)
* **Rule Changes:** See [rule change proposal guidelines](/docs/developer-guide/contributing/rule-changes.md)
* **Other Changes:** See [change proposal guidelines](/docs/developer-guide/contributing/changes.md)
1. Next steps:
* **Questions:** answer the question and close the issue when the conversation is over.
* **Bugs:** if you can verify the bug, add the "accepted" label and ask if they would like to submit a pull request.
* **New Rules:** if you are willing to champion the rule (meaning you believe it should be included in ESLint core and you will take ownership of the process for including it), add a comment saying you will champion the issue, assign the issue to yourself, and follow the [guidelines](#championing-issues) below.
* **Rule Changes:** if you are willing to champion the change and it would not be a breaking change (requiring a major version increment), add a comment saying that you will champion the issue, assign the issue to yourself, and follow the [guidelines](#championing-issues) below.
* **Breaking Changes:** if you suspect or can verify that a change would be breaking, label it as "Breaking".
* **Duplicates:** if you can verify the issue is a duplicate, add a comment mentioning the duplicate issue (such as, "Duplicate of #1234") and close the issue.
1. Regardless of the above, always leave a comment. Don't just add labels, engage with the person who opened the issue by asking a question (request more information if necessary) or stating your opinion of the issue. If it's a verified bug, ask if the user would like to submit a pull request.
**Note:** "Good first issue" issues are intended to help new contributors feel welcome and empowered to make a contribution to ESLint. To ensure that new contributors are given a chance to work on these issues, issues labeled "good first issue" must be open for 30 days *from the day the issue was labeled* before a team member is permitted to work on them.
## Accepting Issues
Issues may be labeled as "accepted" when the issue is:
* A bug that you've been able to reproduce and verify (i.e. you're sure it's a bug)
* A new rule or rule change that you're championing and [consensus](#consensus) has been reached for its inclusion in the project
The "accepted" label will be added to other issues by a TSC member if it's appropriate for the roadmap.
## Championing Issues
New rules and rule changes require a champion. As champion, it's your job to:
* Gain [consensus](#consensus) from the ESLint team on inclusion
* Guide the rule creation process until it's complete (so only champion a rule that you have time to implement or help another contributor implement)
Once consensus has been reached on inclusion, add the "accepted" and, optionally, "help wanted" and "good first issue" labels, as necessary.
## Consensus
Consensus is reached on issues when there are at least three team members who believe the change is a good idea and no one who believes the change is a bad idea. In order to indicate your support for an issue, leave a +1 reaction (thumbs up) on the original issue description in addition to any comments you might have.
## When to Send to TSC
If consensus cannot be reached on an issue, or an issue's progress has been stalled and it's not clear if the issue should be closed, then you can refer the issue to the TSC for resolution. To do so, add the "tsc agenda" label to the issue and add a comment including the following information:
1. A one-paragraph summary of the discussion to this point.
2. The question you would like the TSC to answer.
The issue will be discussed at the next TSC meeting and the resolution will be posted back to the issue.
## Evaluating Core Features and Enhancements (TSC members only)
In addition to the above, changes to the core (including CLI changes) that would result in a minor or major version release must be approved by the TSC by standard TSC motion. Add the label "tsc agenda" to the issue and it will be discussed at the next TSC meeting. In general, requests should meet the following criteria to be considered:
1. The feature or enhancement is in scope for the project and should be added to the roadmap
1. Someone is committed to including the change within the next year
1. There is reasonable certainty about who will do the work
When a suggestion is too ambitious or would take too much time to complete, it's better not to accept the proposal. Stick to small, incremental changes and lay out a roadmap of where you'd like the project to go eventually. Don't let the project get bogged down in big features that will take a long time to complete.
**Breaking Changes:** Be on the lookout for changes that would be breaking. Issues that represent breaking changes should be labeled as "breaking".
## When to Close an Issue
All team members are allowed to close issues depending on how the issue has been resolved.
Team members may close an issue **immediately** if:
1. The issue is a duplicate of an existing issue.
1. The issue is just a question and has been answered.
Team members may close an issue where the consensus is to not accept the issue after a waiting period (to ensure that other team members have a chance to review the issue before it is closed):
* Wait **2 days** if the issue was opened Monday through Friday.
* Wait **3 days** if the issue was opened on Saturday or Sunday.
In an effort to keep the issues backlog manageable, team members may also close an issue if the following conditions are met:
* **Unaccepted**: Close after it has been open for 21 days, as these issues do not have enough support to move forward.
* **Accepted**: Close after 90 days if no one from the team or the community is willing to step forward and own the work to complete to it.
* **Help wanted:** Close after 90 days if it has not been completed.

View File

@ -0,0 +1,16 @@
# npm two-factor authentication
The `eslint` npm account has two-factor authentication (2FA) enabled. The 2FA secret is distributed using a team on [Keybase](https://keybase.io). Anyone doing a release of a package from the Jenkins server needs to have access to the 2FA secret.
If you're on ESLint's TSC, you should perform the following steps to obtain the 2FA secret:
1. Download the [Keybase app](https://keybase.io/download) on a smartphone.
1. Open the app and create an account.
1. From the app, link your Keybase username with your GitHub username. (At the time of writing, the UI for this is to tap the face icon in the bottom-left of the app, then the profile picture in the top-right, then tap "Prove your GitHub" and follow the instructions.)
1. Mention your Keybase username in the team chatroom, and wait for someone to add you to the Keybase team.
1. Download an authenticator app like [Google Authenticator](https://support.google.com/accounts/answer/1066447) or [Authy](https://authy.com/), if you don't have one installed already.
1. In the Keybase app, navigate to the Keybase filesystem (at the time of writing, the UI for this is to tap the hamburger icon in the bottom-right, then tap "Files") and then navigate to `/team/eslint/auth`.
* If your authenticator app is downloaded on the same device as your Keybase app (this will usually be the case if you're using the Keybase mobile app), then open `npm_2fa_code.txt` and copy the contents to the clipboard. Open your authenticator app, and paste the contents as a new key (by selecting something like "Enter a provided key" or "Enter key manually").
* If your authenticator app is downloaded on a *different* device from your Keybase app (e.g. if you're using a Keybase desktop app), then open `npm_2fa_code.png` and scan it as a QR code from your authenticator app.
You should now be able to generate 6-digit 2FA codes for the `eslint` npm account using your authenticator app.

View File

@ -0,0 +1,94 @@
# Reviewing Pull Requests
Pull requests are submitted frequently and represent our best opportunity to interact with the community. As such, it's important that pull requests are well-reviewed before being merged and that interactions on pull requests are positive.
## Who Can Review Pull Requests?
Anyone, both team members and the public, may leave comments on pull requests.
## Reviewing a Pull Request
When a pull request is opened, the bot will check the following:
1. Has the submitter signed a CLA?
1. Is the commit message summary in the correct format?
1. Is the commit summary too long?
The bot will add a comment specifying the problems that it finds. You do not need to look at the pull request any further until those problems have been addressed (there's no need to comment on the pull request to ask the submitter to do what the bot asked - that's why we have the bot!).
Once the bot checks have been satisfied, you check the following:
1. Double-check that the commit message tag ("Fix:", "New:", etc.) is correct based on the issue (or, if no issue is referenced, based on the stated problem).
1. If the pull request makes a change to core, ensure that an issue exists and the pull request references the issue in the commit message.
1. Does the code follow our conventions (including header comments, JSDoc comments, etc.)? If not, please leave that feedback and reference the conventions document.
1. For code changes:
* Are there tests that verify the change? If not, please ask for them.
* Is documentation needed for the change? If yes, please let the submitter know.
1. Are there any automated testing errors? If yes, please ask the submitter to check on them.
1. If you've reviewed the pull request and there are no outstanding issues, leave a comment "LGTM" to indicate your approval. If you would like someone else to verify the change, comment "LGTM but would like someone else to verify."
**Note:** If you are a team member and you've left a comment on the pull request, please follow up to verify that your comments have been addressed.
## Who Can Merge a Pull Request
TSC members and committers may merge pull requests, depending on the contents of the pull request.
Committers may merge a pull request if it is a non-breaking change and is:
1. A documentation change
1. A bug fix (for either rules or core)
1. A dependency upgrade
1. Related to the build tool
1. A chore
In addition, committers may merge any non-breaking pull request if it has been approved by at least one TSC member.
TSC members may merge all pull requests, including those that committers may merge.
## When to Merge a Pull Request
We use the "Merge" button to merge requests into the repository. Before merging a pull request, verify that:
1. All comments have been addressed
1. Any team members who made comments have verified that their concerns were addressed
1. All automated tests are passing (never merge a pull request with failing tests)
Be sure to say thank you to the submitter before merging, especially if they put a lot of work into the pull request.
Team members may merge a pull request immediately if it:
1. Makes a small documentation change
1. Is a chore
1. Fixes a block of other work on the repository (build-related, test-related, dependency-related, etc.)
1. Is an important fix to get into a patch release
Otherwise, team members should observe a waiting period before merging a pull request:
* Wait **2 days** if the pull request was opened Monday through Friday.
* Wait **3 days** if the pull request was opened on Saturday or Sunday.
The waiting period ensures that other team members have a chance to review the pull request before it is merged.
If the pull request was created from a branch on the `eslint/eslint` repository (as opposed to a fork), delete the branch after merging the pull request. (GitHub will display a "Delete branch" button after the pull request is merged.)
**Note:** You should not merge your own pull request unless you're received feedback from at least one other team member.
## When to Close a Pull Request
There are several times when it's appropriate to close a pull request without merging:
1. The pull request addresses an issue that is already fixed
1. The pull request hasn't been updated in 30 days
1. The pull request submitter isn't willing to follow project guidelines.
In any of these cases, please be sure to leave a comment stating why the pull request is being closed.
### Example Closing Comments
If a pull request hasn't been updated in 30 days:
> Closing because there hasn't been activity for 30 days. If you're still interested in submitting this code, please feel free to resubmit.
If a pull request submitter isn't willing to follow project guidelines.
> Unfortunately, we can't accept pull requests that don't follow our guidelines. I'm going to close this pull request now, but if you'd like to resubmit following our guidelines, we'll be happy to review.

View File

@ -0,0 +1,59 @@
# Managing Releases
Releases are when a project formally publishes a new version so the community can use it. There are two types of releases:
* Regular releases that follow [semantic versioning](https://semver.org/) and are considered production-ready.
* Prereleases that are not considered production-ready and are intended to give the community a preview of upcoming changes.
## Release Team
A two-person release team is assigned to each scheduled release. This two-person team is responsible for:
1. The scheduled release on Friday
1. Monitoring issues over the weekend
1. Determining if a patch release is necessary on Monday
1. Publishing the patch release (if necessary)
The two-person team should seek input from the whole team on the Monday following a release to double-check if a patch release is necessary.
At least one member of the release team needs to have access to [eslint's two-factor authentication for npm](./npm-2fa) in order to do a release.
## Release Communication
Each scheduled release should be associated with a release issue ([example](https://github.com/eslint/eslint/issues/8138)). The release issue is the source of information for the team about the status of a release. Be sure the release issue has the "release" label so that it's easy to find.
## Process
On the day of a scheduled release, the release team should follow these steps:
1. Review open pull requests to see if any should be merged. In general, you can merge pull requests that:
* Have been open at least two days and have been reviewed (these are just waiting for merge).
* Important pull requests (as determined by the team). You should stop and have people review before merging if they haven't been already.
* Documentation changes.
* Small bugfixes written by a team member.
1. Log into Jenkins and schedule a build for the "ESLint Release" job.
1. Watch the console output of the build on Jenkins. At some point, the build will pause and a link will be produced with an input field for a six-digit 2FA code.
1. Enter the current six-digit 2FA code from your authenticator app. (Also see: [npm-2fa](./npm-2fa))
1. Continue the build and wait for it to finish.
1. Update the release blog post with a "Highlights" section, including new rules and anything else that's important.
1. Make a release announcement in the public chatroom.
1. Make a release announcement on Twitter.
1. Make a release announcement on the release issue. Document any problems that occurred during the release, and remind the team not to merge anything other than documentation changes and bugfixes. Leave the release issue open.
1. Add the `patch release pending` label to the release issue. (When this label is present, `eslint-github-bot` will create a pending status check on non-semver-patch pull requests, to ensure that they aren't accidentally merged while a patch release is pending.)
On the Monday following the scheduled release, the release team needs to determine if a patch release is necessary. A patch release is considered necessary if any of the following occurred since the scheduled release:
* A regression bug is causing people's lint builds to fail when it previously passed.
* Any bug that is causing a lot of problems for users (frequently happens due to new functionality).
The patch release decision should be made as early on Monday as possible. If a patch release is necessary, then follow the same steps as the scheduled release process.
In rare cases, a second patch release might be necessary if the release is known to have a severe regression that hasn't been fixed by Monday. If this occurs, the release team should announce the situation on the release issue, and leave the issue open until all patch releases are complete. However, it's usually better to fix bugs for the next release cycle rather than doing a second patch release.
After the patch release has been published (or no patch release is necessary), close the release issue and inform the team that they can start merging in semver-minor changes again.
## Emergency Releases
In general, we try not to do emergency releases (an emergency release is unplanned and isn't the regularly scheduled release or the anticipated patch release). Even if there is a regression, it's best to wait the weekend to see if any other problems arise so a patch release can fix as many issues as possible.
The only real exception is if ESLint is completely unusable by most of the current users. For instance, we once pushed a release that errored for everyone because it was missing some core files. In that case, an emergency release is appropriate.

View File

@ -0,0 +1,22 @@
# Working Groups
The ESLint TSC may form working groups to focus on a specific area of the project.
## Creating a Working Group
Working groups are created by sending an email to the team mailing list. Each working group:
1. Must have a GitHub team under the "ESLint Team" top-level GitHub team. (The GitHub team name should end with "WG" to distinguish it from other types of teams.)
1. Must have at least one TSC member.
1. May have any number of Committers and Reviewers.
1. Must have at least two members.
Active working groups are listed on the [team page](https://eslint.org/team).
## How Working Groups Work
Each working group is responsible for its own inner working. Working groups can decide how large or small they should be (so long as there is at least two members), when and who to add or remove from the working group, and how to accomplish their objectives.
Working groups may be temporary or permanent.
If working groups intend to make a significant change to the ESLint project, the proposal must still be approved by the TSC.

View File

@ -0,0 +1,289 @@
# Enforces getter/setter pairs in objects and classes (accessor-pairs)
It's a common mistake in JavaScript to create an object with just a setter for a property but never have a corresponding getter defined for it. Without a getter, you cannot read the property, so it ends up not being used.
Here are some examples:
```js
// Bad
var o = {
set a(value) {
this.val = value;
}
};
// Good
var o = {
set a(value) {
this.val = value;
},
get a() {
return this.val;
}
};
```
This rule warns if setters are defined without getters. Using an option `getWithoutSet`, it will warn if you have a getter without a setter also.
## Rule Details
This rule enforces a style where it requires to have a getter for every property which has a setter defined.
By activating the option `getWithoutSet` it enforces the presence of a setter for every property which has a getter defined.
This rule always checks object literals and property descriptors. By default, it also checks class declarations and class expressions.
## Options
* `setWithoutGet` set to `true` will warn for setters without getters (Default `true`).
* `getWithoutSet` set to `true` will warn for getters without setters (Default `false`).
* `enforceForClassMembers` set to `true` additionally applies this rule to class getters/setters (Default `true`). Set `enforceForClassMembers` to `false` if you want this rule to ignore class declarations and class expressions.
### setWithoutGet
Examples of **incorrect** code for the default `{ "setWithoutGet": true }` option:
```js
/*eslint accessor-pairs: "error"*/
var o = {
set a(value) {
this.val = value;
}
};
var o = {d: 1};
Object.defineProperty(o, 'c', {
set: function(value) {
this.val = value;
}
});
```
Examples of **correct** code for the default `{ "setWithoutGet": true }` option:
```js
/*eslint accessor-pairs: "error"*/
var o = {
set a(value) {
this.val = value;
},
get a() {
return this.val;
}
};
var o = {d: 1};
Object.defineProperty(o, 'c', {
set: function(value) {
this.val = value;
},
get: function() {
return this.val;
}
});
```
### getWithoutSet
Examples of **incorrect** code for the `{ "getWithoutSet": true }` option:
```js
/*eslint accessor-pairs: ["error", { "getWithoutSet": true }]*/
var o = {
set a(value) {
this.val = value;
}
};
var o = {
get a() {
return this.val;
}
};
var o = {d: 1};
Object.defineProperty(o, 'c', {
set: function(value) {
this.val = value;
}
});
var o = {d: 1};
Object.defineProperty(o, 'c', {
get: function() {
return this.val;
}
});
```
Examples of **correct** code for the `{ "getWithoutSet": true }` option:
```js
/*eslint accessor-pairs: ["error", { "getWithoutSet": true }]*/
var o = {
set a(value) {
this.val = value;
},
get a() {
return this.val;
}
};
var o = {d: 1};
Object.defineProperty(o, 'c', {
set: function(value) {
this.val = value;
},
get: function() {
return this.val;
}
});
```
### enforceForClassMembers
When `enforceForClassMembers` is set to `true` (default):
* `"getWithoutSet": true` will also warn for getters without setters in classes.
* `"setWithoutGet": true` will also warn for setters without getters in classes.
Examples of **incorrect** code for `{ "getWithoutSet": true, "enforceForClassMembers": true }`:
```js
/*eslint accessor-pairs: ["error", { "getWithoutSet": true, "enforceForClassMembers": true }]*/
class Foo {
get a() {
return this.val;
}
}
class Bar {
static get a() {
return this.val;
}
}
const Baz = class {
get a() {
return this.val;
}
static set a(value) {
this.val = value;
}
}
```
Examples of **incorrect** code for `{ "setWithoutGet": true, "enforceForClassMembers": true }`:
```js
/*eslint accessor-pairs: ["error", { "setWithoutGet": true, "enforceForClassMembers": true }]*/
class Foo {
set a(value) {
this.val = value;
}
}
const Bar = class {
static set a(value) {
this.val = value;
}
}
```
When `enforceForClassMembers` is set to `false`, this rule ignores classes.
Examples of **correct** code for `{ "getWithoutSet": true, "setWithoutGet": true, "enforceForClassMembers": false }`:
```js
/*eslint accessor-pairs: ["error", {
"getWithoutSet": true, "setWithoutGet": true, "enforceForClassMembers": false
}]*/
class Foo {
get a() {
return this.val;
}
}
class Bar {
static set a(value) {
this.val = value;
}
}
const Baz = class {
static get a() {
return this.val;
}
}
const Quux = class {
set a(value) {
this.val = value;
}
}
```
## Known Limitations
Due to the limits of static analysis, this rule does not account for possible side effects and in certain cases
might not report a missing pair for a getter/setter that has a computed key, like in the following example:
```js
/*eslint accessor-pairs: "error"*/
var a = 1;
// no warnings
var o = {
get [a++]() {
return this.val;
},
set [a++](value) {
this.val = value;
}
};
```
Also, this rule does not disallow duplicate keys in object literals and class definitions, and in certain cases with duplicate keys
might not report a missing pair for a getter/setter, like in the following example:
```js
/*eslint accessor-pairs: "error"*/
// no warnings
var o = {
get a() {
return this.val;
},
a: 1,
set a(value) {
this.val = value;
}
};
```
The code above creates an object with just a setter for the property `"a"`.
See [no-dupe-keys](no-dupe-keys.md) if you also want to disallow duplicate keys in object literals.
See [no-dupe-class-members](no-dupe-class-members.md) if you also want to disallow duplicate names in class definitions.
## When Not To Use It
You can turn this rule off if you are not concerned with the simultaneous presence of setters and getters on objects.
## Further Reading
* [Object Setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set)
* [Object Getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)
* [Working with Objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects)

View File

@ -0,0 +1,281 @@
# enforce line breaks after opening and before closing array brackets (array-bracket-newline)
A number of style guides require or disallow line breaks inside of array brackets.
## Rule Details
This rule enforces line breaks after opening and before closing array brackets.
## Options
This rule has either a string option:
* `"always"` requires line breaks inside brackets
* `"never"` disallows line breaks inside brackets
* `"consistent"` requires consistent usage of linebreaks for each pair of brackets. It reports an error if one bracket in the pair has a linebreak inside it and the other bracket does not.
Or an object option (Requires line breaks if any of properties is satisfied. Otherwise, disallows line breaks):
* `"multiline": true` (default) requires line breaks if there are line breaks inside elements or between elements. If this is false, this condition is disabled.
* `"minItems": null` (default) requires line breaks if the number of elements is at least the given integer. If this is 0, this condition will act the same as the option `"always"`. If this is `null` (the default), this condition is disabled.
### always
Examples of **incorrect** code for this rule with the `"always"` option:
```js
/*eslint array-bracket-newline: ["error", "always"]*/
var a = [];
var b = [1];
var c = [1, 2];
var d = [1,
2];
var e = [function foo() {
dosomething();
}];
```
Examples of **correct** code for this rule with the `"always"` option:
```js
/*eslint array-bracket-newline: ["error", "always"]*/
var a = [
];
var b = [
1
];
var c = [
1, 2
];
var d = [
1,
2
];
var e = [
function foo() {
dosomething();
}
];
```
### never
Examples of **incorrect** code for this rule with the `"never"` option:
```js
/*eslint array-bracket-newline: ["error", "never"]*/
var a = [
];
var b = [
1
];
var c = [
1, 2
];
var d = [
1,
2
];
var e = [
function foo() {
dosomething();
}
];
```
Examples of **correct** code for this rule with the `"never"` option:
```js
/*eslint array-bracket-newline: ["error", "never"]*/
var a = [];
var b = [1];
var c = [1, 2];
var d = [1,
2];
var e = [function foo() {
dosomething();
}];
```
### consistent
Examples of **incorrect** code for this rule with the `"consistent"` option:
```js
/*eslint array-bracket-newline: ["error", "consistent"]*/
var a = [1
];
var b = [
1];
var c = [function foo() {
dosomething();
}
]
var d = [
function foo() {
dosomething();
}]
```
Examples of **correct** code for this rule with the `"consistent"` option:
```js
/*eslint array-bracket-newline: ["error", "consistent"]*/
var a = [];
var b = [
];
var c = [1];
var d = [
1
];
var e = [function foo() {
dosomething();
}];
var f = [
function foo() {
dosomething();
}
];
```
### multiline
Examples of **incorrect** code for this rule with the default `{ "multiline": true }` option:
```js
/*eslint array-bracket-newline: ["error", { "multiline": true }]*/
var a = [
];
var b = [
1
];
var c = [
1, 2
];
var d = [1,
2];
var e = [function foo() {
dosomething();
}];
```
Examples of **correct** code for this rule with the default `{ "multiline": true }` option:
```js
/*eslint array-bracket-newline: ["error", { "multiline": true }]*/
var a = [];
var b = [1];
var c = [1, 2];
var d = [
1,
2
];
var e = [
function foo() {
dosomething();
}
];
```
### minItems
Examples of **incorrect** code for this rule with the `{ "minItems": 2 }` option:
```js
/*eslint array-bracket-newline: ["error", { "minItems": 2 }]*/
var a = [
];
var b = [
1
];
var c = [1, 2];
var d = [1,
2];
var e = [
function foo() {
dosomething();
}
];
```
Examples of **correct** code for this rule with the `{ "minItems": 2 }` option:
```js
/*eslint array-bracket-newline: ["error", { "minItems": 2 }]*/
var a = [];
var b = [1];
var c = [
1, 2
];
var d = [
1,
2
];
var e = [function foo() {
dosomething();
}];
```
### multiline and minItems
Examples of **incorrect** code for this rule with the `{ "multiline": true, "minItems": 2 }` options:
```js
/*eslint array-bracket-newline: ["error", { "multiline": true, "minItems": 2 }]*/
var a = [
];
var b = [
1
];
var c = [1, 2];
var d = [1,
2];
var e = [function foo() {
dosomething();
}];
```
Examples of **correct** code for this rule with the `{ "multiline": true, "minItems": 2 }` options:
```js
/*eslint array-bracket-newline: ["error", { "multiline": true, "minItems": 2 }]*/
var a = [];
var b = [1];
var c = [
1, 2
];
var d = [
1,
2
];
var e = [
function foo() {
dosomething();
}
];
```
## When Not To Use It
If you don't want to enforce line breaks after opening and before closing array brackets, don't enable this rule.
## Compatibility
* **JSCS:** [validateNewlineAfterArrayElements](https://jscs-dev.github.io/rule/validateNewlineAfterArrayElements)
## Related Rules
* [array-bracket-spacing](array-bracket-spacing.md)

View File

@ -0,0 +1,223 @@
# Disallow or enforce spaces inside of brackets (array-bracket-spacing)
A number of style guides require or disallow spaces between array brackets and other tokens. This rule
applies to both array literals and destructuring assignments (ECMAScript 6).
```js
/*eslint-env es6*/
var arr = [ 'foo', 'bar' ];
var [ x, y ] = z;
var arr = ['foo', 'bar'];
var [x,y] = z;
```
## Rule Details
This rule enforces consistent spacing inside array brackets.
## Options
This rule has a string option:
* `"never"` (default) disallows spaces inside array brackets
* `"always"` requires one or more spaces or newlines inside array brackets
This rule has an object option for exceptions to the `"never"` option:
* `"singleValue": true` requires one or more spaces or newlines inside brackets of array literals that contain a single element
* `"objectsInArrays": true` requires one or more spaces or newlines between brackets of array literals and braces of their object literal elements `[ {` or `} ]`
* `"arraysInArrays": true` requires one or more spaces or newlines between brackets of array literals and brackets of their array literal elements `[ [` or `] ]`
This rule has an object option for exceptions to the `"always"` option:
* `"singleValue": false` disallows spaces inside brackets of array literals that contain a single element
* `"objectsInArrays": false` disallows spaces between brackets of array literals and braces of their object literal elements `[{` or `}]`
* `"arraysInArrays": false` disallows spaces between brackets of array literals and brackets of their array literal elements `[[` or `]]`
This rule has built-in exceptions:
* `"never"` (and also the exceptions to the `"always"` option) allows newlines inside array brackets, because this is a common pattern
* `"always"` does not require spaces or newlines in empty array literals `[]`
### never
Examples of **incorrect** code for this rule with the default `"never"` option:
```js
/*eslint array-bracket-spacing: ["error", "never"]*/
/*eslint-env es6*/
var arr = [ 'foo', 'bar' ];
var arr = ['foo', 'bar' ];
var arr = [ ['foo'], 'bar'];
var arr = [[ 'foo' ], 'bar'];
var arr = [ 'foo',
'bar'
];
var [ x, y ] = z;
var [ x,y ] = z;
var [ x, ...y ] = z;
var [ ,,x, ] = z;
```
Examples of **correct** code for this rule with the default `"never"` option:
```js
/*eslint array-bracket-spacing: ["error", "never"]*/
/*eslint-env es6*/
var arr = [];
var arr = ['foo', 'bar', 'baz'];
var arr = [['foo'], 'bar', 'baz'];
var arr = [
'foo',
'bar',
'baz'
];
var arr = ['foo',
'bar'
];
var arr = [
'foo',
'bar'];
var [x, y] = z;
var [x,y] = z;
var [x, ...y] = z;
var [,,x,] = z;
```
### always
Examples of **incorrect** code for this rule with the `"always"` option:
```js
/*eslint array-bracket-spacing: ["error", "always"]*/
/*eslint-env es6*/
var arr = ['foo', 'bar'];
var arr = ['foo', 'bar' ];
var arr = [ ['foo'], 'bar' ];
var arr = ['foo',
'bar'
];
var arr = [
'foo',
'bar'];
var [x, y] = z;
var [x,y] = z;
var [x, ...y] = z;
var [,,x,] = z;
```
Examples of **correct** code for this rule with the `"always"` option:
```js
/*eslint array-bracket-spacing: ["error", "always"]*/
/*eslint-env es6*/
var arr = [];
var arr = [ 'foo', 'bar', 'baz' ];
var arr = [ [ 'foo' ], 'bar', 'baz' ];
var arr = [ 'foo',
'bar'
];
var arr = [
'foo',
'bar' ];
var arr = [
'foo',
'bar',
'baz'
];
var [ x, y ] = z;
var [ x,y ] = z;
var [ x, ...y ] = z;
var [ ,,x, ] = z;
```
### singleValue
Examples of **incorrect** code for this rule with the `"always", { "singleValue": false }` options:
```js
/*eslint array-bracket-spacing: ["error", "always", { "singleValue": false }]*/
var foo = [ 'foo' ];
var foo = [ 'foo'];
var foo = ['foo' ];
var foo = [ 1 ];
var foo = [ 1];
var foo = [1 ];
var foo = [ [ 1, 2 ] ];
var foo = [ { 'foo': 'bar' } ];
```
Examples of **correct** code for this rule with the `"always", { "singleValue": false }` options:
```js
/*eslint array-bracket-spacing: ["error", "always", { "singleValue": false }]*/
var foo = ['foo'];
var foo = [1];
var foo = [[ 1, 1 ]];
var foo = [{ 'foo': 'bar' }];
```
### objectsInArrays
Examples of **incorrect** code for this rule with the `"always", { "objectsInArrays": false }` options:
```js
/*eslint array-bracket-spacing: ["error", "always", { "objectsInArrays": false }]*/
var arr = [ { 'foo': 'bar' } ];
var arr = [ {
'foo': 'bar'
} ]
```
Examples of **correct** code for this rule with the `"always", { "objectsInArrays": false }` options:
```js
/*eslint array-bracket-spacing: ["error", "always", { "objectsInArrays": false }]*/
var arr = [{ 'foo': 'bar' }];
var arr = [{
'foo': 'bar'
}];
```
### arraysInArrays
Examples of **incorrect** code for this rule with the `"always", { "arraysInArrays": false }` options:
```js
/*eslint array-bracket-spacing: ["error", "always", { "arraysInArrays": false }]*/
var arr = [ [ 1, 2 ], 2, 3, 4 ];
var arr = [ [ 1, 2 ], 2, [ 3, 4 ] ];
```
Examples of **correct** code for this rule with the `"always", { "arraysInArrays": false }` options:
```js
/*eslint array-bracket-spacing: ["error", "always", { "arraysInArrays": false }]*/
var arr = [[ 1, 2 ], 2, 3, 4 ];
var arr = [[ 1, 2 ], 2, [ 3, 4 ]];
```
## When Not To Use It
You can turn this rule off if you are not concerned with the consistency of spacing between array brackets.
## Related Rules
* [space-in-parens](space-in-parens.md)
* [object-curly-spacing](object-curly-spacing.md)
* [computed-property-spacing](computed-property-spacing.md)

View File

@ -0,0 +1,154 @@
# Enforces return statements in callbacks of array's methods (array-callback-return)
`Array` has several methods for filtering, mapping, and folding.
If we forget to write `return` statement in a callback of those, it's probably a mistake. If you don't want to use a return or don't need the returned results, consider using [.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) instead.
```js
// example: convert ['a', 'b', 'c'] --> {a: 0, b: 1, c: 2}
var indexMap = myArray.reduce(function(memo, item, index) {
memo[item] = index;
}, {}); // Error: cannot set property 'b' of undefined
```
## Rule Details
This rule enforces usage of `return` statement in callbacks of array's methods.
Additionaly, it may also enforce the `forEach` array method callback to __not__ return a value by using the `checkForEach` option.
This rule finds callback functions of the following methods, then checks usage of `return` statement.
* [`Array.from`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.from)
* [`Array.prototype.every`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.every)
* [`Array.prototype.filter`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.filter)
* [`Array.prototype.find`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.find)
* [`Array.prototype.findIndex`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.findindex)
* [`Array.prototype.flatMap`](https://www.ecma-international.org/ecma-262/10.0/#sec-array.prototype.flatmap)
* [`Array.prototype.forEach`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.foreach) (optional, based on `checkForEach` parameter)
* [`Array.prototype.map`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.map)
* [`Array.prototype.reduce`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.reduce)
* [`Array.prototype.reduceRight`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.reduceright)
* [`Array.prototype.some`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.some)
* [`Array.prototype.sort`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.sort)
* And above of typed arrays.
Examples of **incorrect** code for this rule:
```js
/*eslint array-callback-return: "error"*/
var indexMap = myArray.reduce(function(memo, item, index) {
memo[item] = index;
}, {});
var foo = Array.from(nodes, function(node) {
if (node.tagName === "DIV") {
return true;
}
});
var bar = foo.filter(function(x) {
if (x) {
return true;
} else {
return;
}
});
```
Examples of **correct** code for this rule:
```js
/*eslint array-callback-return: "error"*/
var indexMap = myArray.reduce(function(memo, item, index) {
memo[item] = index;
return memo;
}, {});
var foo = Array.from(nodes, function(node) {
if (node.tagName === "DIV") {
return true;
}
return false;
});
var bar = foo.map(node => node.getAttribute("id"));
```
## Options
This rule accepts a configuration object with two options:
* `"allowImplicit": false` (default) When set to `true`, allows callbacks of methods that require a return value to implicitly return `undefined` with a `return` statement containing no expression.
* `"checkForEach": false` (default) When set to `true`, rule will also report `forEach` callbacks that return a value.
### allowImplicit
Examples of **correct** code for the `{ "allowImplicit": true }` option:
```js
/*eslint array-callback-return: ["error", { allowImplicit: true }]*/
var undefAllTheThings = myArray.map(function(item) {
return;
});
```
### checkForEach
Examples of **incorrect** code for the `{ "checkForEach": true }` option:
```js
/*eslint array-callback-return: ["error", { checkForEach: true }]*/
myArray.forEach(function(item) {
return handleItem(item)
});
myArray.forEach(function(item) {
if (item < 0) {
return x;
}
handleItem(item);
});
myArray.forEach(item => handleItem(item));
myArray.forEach(item => {
return handleItem(item);
});
```
Examples of **correct** code for the `{ "checkForEach": true }` option:
```js
/*eslint array-callback-return: ["error", { checkForEach: true }]*/
myArray.forEach(function(item) {
handleItem(item)
});
myArray.forEach(function(item) {
if (item < 0) {
return;
}
handleItem(item);
});
myArray.forEach(function(item) {
handleItem(item);
return;
});
myArray.forEach(item => {
handleItem(item);
});
```
## Known Limitations
This rule checks callback functions of methods with the given names, *even if* the object which has the method is *not* an array.
## When Not To Use It
If you don't want to warn about usage of `return` statement in callbacks of array's methods, then it's safe to disable this rule.

Some files were not shown because too many files have changed in this diff Show More