Merge branch 'text-utils-javacc' into text-utils-comments

This commit is contained in:
Clément Fournier
2022-04-30 21:02:08 +02:00
399 changed files with 17094 additions and 12493 deletions

View File

@ -6584,6 +6584,61 @@
"contributions": [
"code"
]
},
{
"login": "jasonqiu98",
"name": "Jason Qiu",
"avatar_url": "https://avatars.githubusercontent.com/u/26801257?v=4",
"profile": "https://github.com/jasonqiu98",
"contributions": [
"code",
"doc"
]
},
{
"login": "laoseth",
"name": "Seth Wilcox",
"avatar_url": "https://avatars.githubusercontent.com/u/16923065?v=4",
"profile": "https://github.com/laoseth",
"contributions": [
"code"
]
},
{
"login": "LiGaOg",
"name": "LiGaOg",
"avatar_url": "https://avatars.githubusercontent.com/u/72175888?v=4",
"profile": "https://github.com/LiGaOg",
"contributions": [
"code"
]
},
{
"login": "Scrsloota",
"name": "Scrsloota",
"avatar_url": "https://avatars.githubusercontent.com/u/91131546?v=4",
"profile": "https://github.com/Scrsloota",
"contributions": [
"code"
]
},
{
"login": "VoidxHoshi",
"name": "LaLucid",
"avatar_url": "https://avatars.githubusercontent.com/u/55886143?v=4",
"profile": "https://github.com/VoidxHoshi",
"contributions": [
"code"
]
},
{
"login": "naveensrinivasan",
"name": "Naveen",
"avatar_url": "https://avatars.githubusercontent.com/u/172697?v=4",
"profile": "https://naveensrinivasan.dev/",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,

View File

@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: |
~/.m2/repository

View File

@ -2,6 +2,9 @@ name: troubleshooting
on: workflow_dispatch
permissions:
contents: read
jobs:
build:
runs-on: ${{ matrix.os }}
@ -13,7 +16,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v2
- uses: actions/cache@v3
with:
path: |
~/.m2/repository

View File

@ -42,7 +42,7 @@ def run_pmdtester
@base_branch = 'master'
@logger.info "\n\n--------------------------------------"
@logger.info "Run against #{@base_branch}"
@summary = PmdTester::Runner.new(get_args(@base_branch)).run
@summary = PmdTester::Runner.new(get_args(@base_branch, FALSE, 'target/diff1/patch_config.xml')).run
# move the generated report out of the way
FileUtils.mv 'target/reports/diff', 'target/diff2'

View File

@ -12,7 +12,7 @@ GEM
concurrent-ruby (1.1.10)
cork (0.3.0)
colored2 (~> 3.1)
danger (8.5.0)
danger (8.6.1)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
colored2 (~> 3.1)
@ -53,12 +53,12 @@ GEM
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
fugit (1.5.2)
et-orbi (~> 1.1, >= 1.1.8)
fugit (1.5.3)
et-orbi (~> 1, >= 1.2.7)
raabro (~> 1.4)
git (1.10.2)
git (1.11.0)
rchardet (~> 1.8)
kramdown (2.3.2)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
@ -68,21 +68,21 @@ GEM
multipart-post (2.1.1)
nap (1.1.0)
no_proxy_fix (0.1.2)
nokogiri (1.13.3)
nokogiri (1.13.4)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
octokit (4.22.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
open4 (1.3.4)
pmdtester (1.4.0)
pmdtester (1.4.1)
differ (~> 0.1)
liquid (~> 5.2)
logger-colors (~> 1.0)
nokogiri (~> 1.13)
rufus-scheduler (~> 3.8)
slop (~> 4.6)
public_suffix (4.0.6)
public_suffix (4.0.7)
raabro (1.4.0)
racc (1.6.0)
rchardet (1.8.0)
@ -95,7 +95,7 @@ GEM
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
slop (4.9.1)
slop (4.9.2)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
tzinfo (2.0.4)

View File

@ -1,7 +1,7 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (6.0.4.7)
activesupport (6.0.4.8)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@ -15,7 +15,7 @@ GEM
coffee-script-source (1.11.1)
colorator (1.1.0)
commonmarker (0.23.4)
concurrent-ruby (1.1.9)
concurrent-ruby (1.1.10)
dnsruby (1.61.9)
simpleidn (~> 0.1)
em-websocket (0.5.3)
@ -51,9 +51,9 @@ GEM
ffi (1.15.5)
forwardable-extended (2.6.0)
gemoji (3.0.1)
github-pages (225)
github-pages (226)
github-pages-health-check (= 1.17.9)
jekyll (= 3.9.0)
jekyll (= 3.9.2)
jekyll-avatar (= 0.7.0)
jekyll-coffeescript (= 1.1.1)
jekyll-commonmark-ghpages (= 0.2.0)
@ -88,12 +88,12 @@ GEM
jekyll-theme-time-machine (= 0.2.0)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.12.0)
kramdown (= 2.3.1)
kramdown (= 2.3.2)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.3)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.12.5, < 2.0)
nokogiri (>= 1.13.4, < 2.0)
rouge (= 3.26.0)
terminal-table (~> 1.4)
github-pages-health-check (1.17.9)
@ -102,13 +102,13 @@ GEM
octokit (~> 4.0)
public_suffix (>= 3.0, < 5.0)
typhoeus (~> 1.3)
html-pipeline (2.14.0)
html-pipeline (2.14.1)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.8.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.9.0)
jekyll (3.9.2)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
@ -216,7 +216,7 @@ GEM
gemoji (~> 3.0)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
kramdown (2.3.1)
kramdown (2.3.2)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
@ -232,7 +232,7 @@ GEM
jekyll-seo-tag (~> 2.1)
minitest (5.15.0)
multipart-post (2.1.1)
nokogiri (1.13.3)
nokogiri (1.13.4)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
octokit (4.22.0)
@ -240,7 +240,7 @@ GEM
sawyer (~> 0.8.0, >= 0.5.3)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.6)
public_suffix (4.0.7)
racc (1.6.0)
rb-fsevent (0.11.1)
rb-inotify (0.10.1)
@ -269,7 +269,7 @@ GEM
thread_safe (~> 0.1)
unf (0.1.4)
unf_ext
unf_ext (0.0.8)
unf_ext (0.0.8.1)
unicode-display_width (1.8.0)
zeitwerk (2.5.4)

View File

@ -2,7 +2,7 @@ repository: pmd/pmd
pmd:
version: 7.0.0-SNAPSHOT
previous_version: 6.44.0
previous_version: 6.45.0
date: ??-?????-2022
release_type: major

View File

@ -175,6 +175,18 @@ entries:
- title: Error Prone
output: web, pdf
url: /pmd_rules_ecmascript_errorprone.html
- title: null
output: web, pdf
subfolders:
- title: HTML Rules
output: web, pdf
subfolderitems:
- title: Index
output: web, pdf
url: /pmd_rules_html.html
- title: Best Practices
output: web, pdf
url: /pmd_rules_html_bestpractices.html
- title: null
output: web, pdf
subfolders:
@ -379,6 +391,9 @@ entries:
- title: XML and XML dialects
url: /pmd_languages_xml.html
output: web, pdf
- title: HTML
url: /pmd_languages_html.html
output: web, pdf
- title: Developer Documentation
output: web, pdf
folderitems:

View File

@ -2,6 +2,7 @@
<ul id="mysidebar" class="nav">
<li class="sidebarTitle">{{sidebar[0].product}} {{sidebar[0].version | replace: '!PMD_VERSION!', site.pmd.version}}</li>
<div class="sidebarTitleDate">Release date: {{site.pmd.date}}</div>
{% for entry in sidebar %}
{% for folder in entry.folders %}
{% if folder.output contains "web" %}

View File

@ -122,3 +122,9 @@ pre {
border: 1px solid #cccccc;
border-radius: 4px;
}
div.sidebarTitleDate {
margin-top:2.5px;
margin-bottom:5px;
margin-left:5px;
}

View File

@ -97,7 +97,7 @@ li.sidebarTitle {
font-weight:normal;
font-size:130%;
color: #ED1951;
margin-bottom:10px;
margin-left: 5px;
margin-bottom:2.5px;
margin-left:5px;
}

View File

@ -84,7 +84,6 @@ li.sidebarTitle {
font-weight:normal;
font-size:130%;
color: #4d94ff;
margin-bottom:10px;
margin-left: 5px;
margin-bottom:2.5px;
margin-left:5px;
}

View File

@ -19,6 +19,15 @@ This is a {{ site.pmd.release_type }} release.
### New and noteworthy
#### CLI improvements
The PMD CLI has been enhanced with a progress bar, which interactively displays the
current progress of the analysis.
TODO screenshot (take it right before releasing, because other changes to the CLI will occur until then)
This can be disabled with the `--no-progress` flag.
#### Full Antlr support
Languages backed by an Antlr grammar are now fully supported. This means, it's now possible not only to use Antlr grammars for CPD,
@ -155,7 +164,8 @@ The following previously deprecated rules have been finally removed:
* miscellaneous
* [#896](https://github.com/pmd/pmd/issues/896): \[all] Use slf4j
* [#1451](https://github.com/pmd/pmd/issues/1451): \[core] RulesetFactoryCompatibility stores the whole ruleset file in memory as a string
* cli
* [#3828](https://github.com/pmd/pmd/issues/3828): \[core] Progress reporting
* apex-design
* [#2667](https://github.com/pmd/pmd/issues/2667): \[apex] Integrate nawforce/ApexLink to build robust Unused rule
* java-bestpractices
@ -279,6 +289,7 @@ The metrics framework has been made simpler and more general.
* [#1881](https://github.com/pmd/pmd/pull/1881): \[doc] Add ANTLR documentation - [Matías Fraga](https://github.com/matifraga)
* [#1882](https://github.com/pmd/pmd/pull/1882): \[swift] UnavailableFunction Swift rule - [Tomás de Lucca](https://github.com/tomidelucca)
* [#2830](https://github.com/pmd/pmd/pull/2830): \[apex] Apexlink POC - [Kevin Jones](https://github.com/nawforce)
* [#3866](https://github.com/pmd/pmd/pull/3866): \[core] Add CLI Progress Bar - [@JerritEic](https://github.com/JerritEic)
{% endtocmaker %}

View File

@ -246,6 +246,18 @@ the breaking API changes will be performed in 7.0.0.
an API is tagged as `@Deprecated` or not in the latest minor release. During the development of 7.0.0,
we may decide to remove some APIs that were not tagged as deprecated, though we'll try to avoid it." %}
#### 6.45.0
##### Experimental APIs
* Report has two new methods which allow limited mutations of a given report:
* {% jdoc !!core::Report#filterViolations(net.sourceforge.pmd.util.Predicate) %} creates a new report with
some violations removed with a given predicate based filter.
* {% jdoc !!core::Report#union(net.sourceforge.pmd.Report) %} can combine two reports into a single new Report.
* {% jdoc !!core::util.Predicate %} will be replaced in PMD7 with the standard Predicate interface from java8.
* The module `pmd-html` is entirely experimental right now. Anything in the package
`net.sourceforge.pmd.lang.html` should be used cautiously.
#### 6.44.0
##### Deprecated API

View File

@ -0,0 +1,18 @@
---
title: Processing HTML files
permalink: pmd_languages_html.html
last_updated: April 2022 (6.45.0)
---
## The HTML language module
**Since:** 6.45.0
**Minimum Java Runtime:** Java 8
{% include warning.html content="This language module is experimental and may change any time." %}
The HTML language module uses [jsoup](https://jsoup.org/) for parsing.
XPath rules are supported, but the DOM is not a typical XML/XPath DOM. E.g.
text nodes are normal nodes. This might change in the future.

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,132 @@ permalink: pmd_release_notes_old.html
Previous versions of PMD can be downloaded here: https://github.com/pmd/pmd/releases
## 30-April-2022 - 6.45.0
The PMD team is pleased to announce PMD 6.45.0.
This is a minor release.
### Table Of Contents
* [New and noteworthy](#new-and-noteworthy)
* [PMD User Survey](#pmd-user-survey)
* [Support for HTML](#support-for-html)
* [New rules](#new-rules)
* [Modified rules](#modified-rules)
* [Fixed Issues](#fixed-issues)
* [API Changes](#api-changes)
* [Experimental APIs](#experimental-apis)
* [External Contributions](#external-contributions)
* [Stats](#stats)
### New and noteworthy
#### PMD User Survey
Help shape the future of PMD by telling us how you use it.
Our little survey is still open in case you didn't participate yet.
Please participate in our survey at <https://forms.gle/4d8r1a1RDzfixHDc7>.
Thank you!
#### Support for HTML
This version of PMD ships a new language module to support analyzing of HTML.
Support for HTML is experimental and might change without notice.
The language implementation is not complete yet and the AST doesn't look
well for text nodes and comment nodes and might be changed in the future.
You can write your own rules, but we don't guarantee that the rules work with
the next (minor) version of PMD without adjustments.
Please give us feedback about how practical this new language is in
[discussions](https://github.com/pmd/pmd/discussions). Please report
missing features or bugs as new [issues](https://github.com/pmd/pmd/issues).
#### New rules
* The HTML rule [`AvoidInlineStyles`](https://pmd.github.io/pmd-6.45.0/pmd_rules_html_bestpractices.html#avoidinlinestyles) finds elements which use a style attribute.
In order to help maintaining a webpage it is considered good practice to separate content and styles. Instead
of inline styles one should use CSS files and classes.
```xml
<rule ref="category/html/bestpractices.xml/AvoidInlineStyles" />
```
* The HTML rule [`UnnecessaryTypeAttribute`](https://pmd.github.io/pmd-6.45.0/pmd_rules_html_bestpractices.html#unnecessarytypeattribute) finds "link" and "script" elements which
still have a "type" attribute. This is not necessary anymore since modern browsers automatically use CSS and
JavaScript.
```xml
<rule ref="category/html/bestpractices.xml/UnnecessaryTypeAttribute" />
```
* The HTML rule [`UseAltAttributeForImages`](https://pmd.github.io/pmd-6.45.0/pmd_rules_html_bestpractices.html#usealtattributeforimages) finds "img" elements without an "alt"
attribute. An alternate text should always be provided in order to help screen readers.
```xml
<rule ref="category/html/bestpractices.xml/UseAltAttributeForImages" />
```
#### Modified rules
* The Java rule [`UnusedPrivateField`](https://pmd.github.io/pmd-6.45.0/pmd_rules_java_bestpractices.html#unusedprivatefield) has a new property `ignoredFieldNames`.
The default ignores serialization-specific fields (eg `serialVersionUID`).
The property can be used to ignore more fields based on their name.
Note that the rule used to ignore fields named `IDENT`, but doesn't anymore (add this value to the property to restore the old behaviour).
### Fixed Issues
* core
* [#3792](https://github.com/pmd/pmd/issues/3792): \[core] Allow to filter violations in Report
* [#3881](https://github.com/pmd/pmd/issues/3881): \[core] SARIF renderer depends on platform default encoding
* [#3882](https://github.com/pmd/pmd/pull/3882): \[core] Fix AssertionError about exhaustive switch
* [#3884](https://github.com/pmd/pmd/issues/3884): \[core] XML report via ant task contains XML header twice
* [#3896](https://github.com/pmd/pmd/pull/3896): \[core] Fix ast-dump CLI when reading from stdin
* doc
* [#2505](https://github.com/pmd/pmd/issues/2505): \[doc] Improve side bar to show release date
* java
* [#3068](https://github.com/pmd/pmd/issues/3068): \[java] Some tests should not depend on real rules
* [#3889](https://github.com/pmd/pmd/pull/3889): \[java] Catch LinkageError in UselessOverridingMethodRule
* java-bestpractices
* [#3910](https://github.com/pmd/pmd/pull/3910): \[java] UnusedPrivateField - Allow the ignored fieldnames to be configurable
* [#1185](https://github.com/pmd/pmd/issues/1185): \[java] ArrayIsStoredDirectly false positive with field access
* [#1474](https://github.com/pmd/pmd/issues/1474): \[java] ArrayIsStoredDirectly false positive with method call
* [#3879](https://github.com/pmd/pmd/issues/3879) \[java] ArrayIsStoredDirectly reports duplicated violation
* [#3929](https://github.com/pmd/pmd/issues/3929): \[java] ArrayIsStoredDirectly should report the assignment rather than formal parameter
* java-design
* [#3603](https://github.com/pmd/pmd/issues/3603): \[java] SimplifiedTernary: no violation for 'condition ? true : false' case
* java-performance
* [#3867](https://github.com/pmd/pmd/issues/3867): \[java] UseArraysAsList with method call
* plsql
* [#3687](https://github.com/pmd/pmd/issues/3687): \[plsql] Parsing exception EXECUTE IMMEDIATE l_sql BULK COLLECT INTO statement
* [#3706](https://github.com/pmd/pmd/issues/3706): \[plsql] Parsing exception CURSOR statement with parenthesis groupings
### API Changes
#### Experimental APIs
* Report has two new methods which allow limited mutations of a given report:
* <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.45.0/net/sourceforge/pmd/Report.html#filterViolations(net.sourceforge.pmd.util.Predicate)"><code>Report#filterViolations</code></a> creates a new report with
some violations removed with a given predicate based filter.
* <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.45.0/net/sourceforge/pmd/Report.html#union(net.sourceforge.pmd.Report)"><code>Report#union</code></a> can combine two reports into a single new Report.
* <a href="https://docs.pmd-code.org/apidocs/pmd-core/6.45.0/net/sourceforge/pmd/util/Predicate.html#"><code>net.sourceforge.pmd.util.Predicate</code></a> will be replaced in PMD7 with the standard Predicate interface from java8.
* The module `pmd-html` is entirely experimental right now. Anything in the package
`net.sourceforge.pmd.lang.html` should be used cautiously.
### External Contributions
* [#3883](https://github.com/pmd/pmd/pull/3883): \[doc] Improve side bar by Adding Release Date - [@jasonqiu98](https://github.com/jasonqiu98)
* [#3910](https://github.com/pmd/pmd/pull/3910): \[java] UnusedPrivateField - Allow the ignored fieldnames to be configurable - [@laoseth](https://github.com/laoseth)
* [#3928](https://github.com/pmd/pmd/pull/3928): \[plsql] Fix plsql parsing error in parenthesis groups - [@LiGaOg](https://github.com/LiGaOg)
* [#3935](https://github.com/pmd/pmd/pull/3935): \[plsql] Fix parser exception in EXECUTE IMMEDIATE BULK COLLECT #3687 - [@Scrsloota](https://github.com/Scrsloota)
* [#3938](https://github.com/pmd/pmd/pull/3938): \[java] Modify SimplifiedTernary to meet the missing case #3603 - [@VoidxHoshi](https://github.com/VoidxHoshi)
* [#3943](https://github.com/pmd/pmd/pull/3943): chore: Set permissions for GitHub actions - [@naveensrinivasan](https://github.com/naveensrinivasan)
### Stats
* 97 commits
* 31 closed tickets & PRs
* Days since last release: 33
## 27-March-2022 - 6.44.0
The PMD team is pleased to announce PMD 6.44.0.
@ -14,6 +140,7 @@ This is a minor release.
### Table Of Contents
* [New and noteworthy](#new-and-noteworthy)
* [PMD User Survey](#pmd-user-survey)
* [Java 18 Support](#java-18-support)
* [Better XML XPath support](#better-xml-xpath-support)
* [New XPath functions](#new-xpath-functions)
@ -27,6 +154,14 @@ This is a minor release.
### New and noteworthy
#### PMD User Survey
Help shape the future of PMD by telling us how you use it.
Please participate in our survey at <https://forms.gle/4d8r1a1RDzfixHDc7>.
Thank you!
#### Java 18 Support
This release of PMD brings support for Java 18. There are no new standard language features.

View File

@ -41,10 +41,10 @@ public final class ASTMethodCallExpression extends AbstractApexNode<MethodCallEx
}
@Override
protected @NonNull TextRegion getRegion() {
public @NonNull TextRegion getTextRegion() {
int fullLength = getFullMethodName().length();
int nameLength = getMethodName().length();
TextRegion base = super.getRegion();
TextRegion base = super.getTextRegion();
if (fullLength > nameLength) {
base = base.growLeft(fullLength - nameLength);
}

View File

@ -10,7 +10,6 @@ import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.lang.ast.AstVisitor;
import net.sourceforge.pmd.lang.ast.FileAnalysisException;
import net.sourceforge.pmd.lang.ast.impl.AbstractNode;
import net.sourceforge.pmd.lang.document.FileLocation;
import net.sourceforge.pmd.lang.document.TextDocument;
import net.sourceforge.pmd.lang.document.TextRegion;
@ -57,18 +56,14 @@ abstract class AbstractApexNode<T extends AstNode> extends AbstractNode<Abstract
}
@Override
public FileLocation getReportLocation() {
return getTextDocument().toLocation(getRegion());
}
protected @NonNull TextRegion getRegion() {
public @NonNull TextRegion getTextRegion() {
if (region == null) {
if (!hasRealLoc()) {
AbstractApexNode<?> parent = (AbstractApexNode<?>) getParent();
if (parent == null) {
throw new FileAnalysisException("Unable to determine location of " + this);
}
region = parent.getRegion();
region = parent.getTextRegion();
} else {
Location loc = node.getLoc();
region = TextRegion.fromBothOffsets(loc.getStartIndex(), loc.getEndIndex());

View File

@ -390,7 +390,7 @@ final class ApexTreeBuilder extends AstVisitor<AdditionalPassScope> {
return;
}
// find the token, that appears as close as possible before the node
TextRegion nodeRegion = node.getRegion();
TextRegion nodeRegion = node.getTextRegion();
for (ApexDocTokenLocation comment : commentInfo.docTokenLocations) {
if (comment.region.compareTo(nodeRegion) > 0) {
// this and all remaining tokens are after the node
@ -436,8 +436,8 @@ final class ApexTreeBuilder extends AstVisitor<AdditionalPassScope> {
if (checkForCommentSuppression && commentText.startsWith("//")) {
Chars trimmed = commentText.subSequence("//".length(), commentText.length()).trimStart();
if (trimmed.startsWith(suppressMarker)) {
Chars userMessage = trimmed.subSequence(suppressMarker.length(), trimmed.length()).trim();
suppressMap.put(source.lineNumberAt(startIdx), userMessage.toString());
Chars userMessage = trimmed.subSequence(suppressMarker.length()).trim();
suppressMap.put(source.lineColumnAtOffset(startIdx).getLine(), userMessage.toString());
}
}
}

View File

@ -4,10 +4,12 @@
package net.sourceforge.pmd.lang.apex.ast;
import static net.sourceforge.pmd.lang.ast.test.NodeExtensionsKt.textOfReportLocation;
import static net.sourceforge.pmd.lang.ast.test.TestUtilsKt.assertPosition;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
@ -18,7 +20,6 @@ import java.util.List;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import net.sourceforge.pmd.lang.ast.Node;
@ -75,22 +76,22 @@ public class ApexParserTest extends ApexParserTestBase {
assertLineNumbersForTestCode(rootNode);
}
private void assertLineNumbersForTestCode(ASTUserClassOrInterface<?> rootNode) {
private void assertLineNumbersForTestCode(ASTUserClassOrInterface<?> classNode) {
// whole source code, well from the beginning of the class
// name Modifier of the class - doesn't work. This node just
// sees the identifier ("SimpleClass")
// assertPosition(rootNode.getChild(0), 1, 1, 1, 6);
// "public"
assertPosition(rootNode, 1, 14, 1, 25);
// identifier: "SimpleClass"
assertPosition(classNode, 1, 14, 1, 25);
assertTextEquals("SimpleClass", classNode);
// "method1" - starts with identifier until end of its block statement
Node method1 = rootNode.getChild(1);
// identifier: "method1"
Node method1 = classNode.getChild(1);
assertTextEquals("method1", method1);
assertPosition(method1, 2, 17, 2, 24);
// Modifier of method1 - doesn't work. This node just sees the
// identifier ("method1")
// assertPosition(method1.getChild(0), 2, 17, 2, 20); // "public" for
// method1
// modifiers have same location
assertPosition(method1.getChild(0), 2, 17, 2, 24);
// BlockStatement - the whole method body
Node blockStatement = method1.getChild(1);
@ -100,6 +101,7 @@ public class ApexParserTest extends ApexParserTestBase {
// the expression ("System.out...")
Node expressionStatement = blockStatement.getChild(0);
assertPosition(expressionStatement, 3, 20, 3, 35);
assertTextEquals("println('abc');", expressionStatement);
}
@Test
@ -189,36 +191,36 @@ public class ApexParserTest extends ApexParserTestBase {
}
@Test
@Ignore("This is buggy, I'd like to stop pretending our reportLocation is a real node position")
public void verifyLineColumnNumbersInnerClasses() throws Exception {
public void verifyLineColumnNumbersInnerClasses() {
ASTApexFile rootNode = apex.parseResource("InnerClassLocations.cls");
Assert.assertNotNull(rootNode);
visitPosition(rootNode, 0);
Assert.assertEquals("InnerClassLocations", rootNode.getMainNode().getSimpleName());
ASTUserClassOrInterface<?> classNode = rootNode.getMainNode();
Assert.assertEquals("InnerClassLocations", classNode.getSimpleName());
assertTextEquals("InnerClassLocations", classNode);
// Note: Apex parser doesn't provide positions for "public class" keywords. The
// position of the UserClass node is just the identifier. So, the node starts
// with the identifier and not with the first keyword in the file...
assertPosition(rootNode, 1, 14, 16, 2);
assertPosition(classNode, 1, 14, 1, 33);
List<ASTUserClass> classes = rootNode.descendants(ASTUserClass.class).toList();
List<ASTUserClass> classes = classNode.descendants(ASTUserClass.class).toList();
Assert.assertEquals(2, classes.size());
Assert.assertEquals("bar1", classes.get(0).getSimpleName());
List<ASTMethod> methods = classes.get(0).children(ASTMethod.class).toList();
Assert.assertEquals(2, methods.size()); // m() and synthetic clone()
Assert.assertEquals("m", methods.get(0).getImage());
assertPosition(methods.get(0), 4, 21, 7, 9);
assertPosition(methods.get(0), 4, 21, 4, 22);
Assert.assertEquals("clone", methods.get(1).getImage());
assertPosition(methods.get(1), 7, 9, 7, 9);
assertFalse(methods.get(1).hasRealLoc());
assertPosition(methods.get(1), 3, 18, 3, 22);
// Position of the first inner class: starts with the identifier "bar1" and ends with
// the last real method m(). The last bracket it actually on the next line 8, but we
// don't see this in the AST.
assertPosition(classes.get(0), 3, 18, 7, 9);
// Position of the first inner class is its identifier
assertPosition(classes.get(0), 3, 18, 3, 22);
Assert.assertEquals("bar2", classes.get(1).getImage());
assertPosition(classes.get(1), 10, 18, 14, 9);
Assert.assertEquals("bar2", classes.get(1).getSimpleName());
assertPosition(classes.get(1), 10, 18, 10, 22);
}
// TEST HELPER
@ -226,8 +228,8 @@ public class ApexParserTest extends ApexParserTestBase {
private int visitPosition(Node node, int count) {
int result = count + 1;
FileLocation loc = node.getReportLocation();
Assert.assertTrue(loc.getBeginLine() > 0);
Assert.assertTrue(loc.getBeginColumn() > 0);
Assert.assertTrue(loc.getStartLine() > 0);
Assert.assertTrue(loc.getStartColumn() > 0);
Assert.assertTrue(loc.getEndLine() > 0);
Assert.assertTrue(loc.getEndColumn() > 0);
for (int i = 0; i < node.getNumChildren(); i++) {
@ -235,4 +237,8 @@ public class ApexParserTest extends ApexParserTestBase {
}
return result;
}
private void assertTextEquals(String expected, Node expressionStatement) {
assertEquals(expected, textOfReportLocation(expressionStatement));
}
}

View File

@ -1,99 +1,99 @@
+- ApexFile[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
+- UserClass[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "Foo", @Namespace = "", @RealLoc = "true", @SimpleName = "Foo", @SuperClassName = ""]
+- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "1", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "true", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
+- Field[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "x", @Name = "x", @Namespace = "", @RealLoc = "true", @Type = "Integer", @Value = null]
| +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
+- Field[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "profileUrl", @Name = "profileUrl", @Namespace = "", @RealLoc = "true", @Type = "String", @Value = null]
| +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
+- FieldDeclarationStatements[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true", @TypeName = "Integer"]
| +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "false", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
| +- FieldDeclaration[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "anIntegerField", @Name = "anIntegerField", @Namespace = "", @RealLoc = "true"]
| +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "anIntegerField", @Namespace = "", @RealLoc = "true"]
| | +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "LOAD", @SObjectType = "false", @SafeNav = "true"]
| | +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "anObject", @Namespace = "", @RealLoc = "true"]
| | +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
| +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "x", @Namespace = "", @RealLoc = "true"]
| +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
+- FieldDeclarationStatements[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true", @TypeName = "String"]
| +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "false", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
| +- FieldDeclaration[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "profileUrl", @Name = "profileUrl", @Namespace = "", @RealLoc = "true"]
| +- MethodCallExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @FullMethodName = "toExternalForm", @InputParametersSize = "0", @MethodName = "toExternalForm", @Namespace = "", @RealLoc = "true"]
| | +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "METHOD", @SObjectType = "false", @SafeNav = "true"]
| | +- MethodCallExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @FullMethodName = "user.getProfileUrl", @InputParametersSize = "0", @MethodName = "getProfileUrl", @Namespace = "", @RealLoc = "true"]
| | +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Image = "user", @Namespace = "", @RealLoc = "true", @ReferenceType = "METHOD", @SObjectType = "false", @SafeNav = "false"]
| +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "profileUrl", @Namespace = "", @RealLoc = "true"]
| +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
+- Method[@ApexVersion = "54.0", @Arity = "1", @CanonicalName = "bar1", @Constructor = "false", @DefiningType = "Foo", @Image = "bar1", @Namespace = "", @RealLoc = "true", @ReturnType = "void", @Synthetic = "false"]
| +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "1", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "true", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
| +- Parameter[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "a", @Namespace = "", @RealLoc = "true", @Type = "Object"]
| | +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
| +- BlockStatement[@ApexVersion = "54.0", @CurlyBrace = "true", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| +- ExpressionStatement[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| | +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "b", @Namespace = "", @RealLoc = "true"]
| | +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "LOAD", @SObjectType = "false", @SafeNav = "true"]
| | +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "a", @Namespace = "", @RealLoc = "true"]
| | +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
| +- ExpressionStatement[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| +- MethodCallExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @FullMethodName = "c1", @InputParametersSize = "0", @MethodName = "c1", @Namespace = "", @RealLoc = "true"]
| +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "METHOD", @SObjectType = "false", @SafeNav = "true"]
| +- CastExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "b1", @Namespace = "", @RealLoc = "true"]
| +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "LOAD", @SObjectType = "false", @SafeNav = "true"]
| +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "a1", @Namespace = "", @RealLoc = "true"]
| +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
+- Method[@ApexVersion = "54.0", @Arity = "2", @CanonicalName = "bar2", @Constructor = "false", @DefiningType = "Foo", @Image = "bar2", @Namespace = "", @RealLoc = "true", @ReturnType = "void", @Synthetic = "false"]
| +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "1", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "true", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
| +- Parameter[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "a", @Namespace = "", @RealLoc = "true", @Type = "List<Object>"]
| | +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
| +- Parameter[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "x", @Namespace = "", @RealLoc = "true", @Type = "int"]
| | +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
| +- BlockStatement[@ApexVersion = "54.0", @CurlyBrace = "true", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| +- ExpressionStatement[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| | +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "aField", @Namespace = "", @RealLoc = "true"]
| | +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "LOAD", @SObjectType = "false", @SafeNav = "false"]
| | +- MethodCallExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @FullMethodName = "aMethod", @InputParametersSize = "0", @MethodName = "aMethod", @Namespace = "", @RealLoc = "true"]
| | +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "METHOD", @SObjectType = "false", @SafeNav = "true"]
| | +- ArrayLoadExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| | +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "a", @Namespace = "", @RealLoc = "true"]
| | | +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
| | +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "x", @Namespace = "", @RealLoc = "true"]
| | +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
| +- ExpressionStatement[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "aField", @Namespace = "", @RealLoc = "true"]
| +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "LOAD", @SObjectType = "false", @SafeNav = "true"]
| +- MethodCallExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @FullMethodName = "aMethod", @InputParametersSize = "0", @MethodName = "aMethod", @Namespace = "", @RealLoc = "true"]
| +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "METHOD", @SObjectType = "false", @SafeNav = "false"]
| +- ArrayLoadExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "a", @Namespace = "", @RealLoc = "true"]
| | +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
| +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "x", @Namespace = "", @RealLoc = "true"]
| +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
+- Method[@ApexVersion = "54.0", @Arity = "1", @CanonicalName = "getName", @Constructor = "false", @DefiningType = "Foo", @Image = "getName", @Namespace = "", @RealLoc = "true", @ReturnType = "String", @Synthetic = "false"]
| +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "1", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "true", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
| +- Parameter[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "accId", @Namespace = "", @RealLoc = "true", @Type = "int"]
| | +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
| +- BlockStatement[@ApexVersion = "54.0", @CurlyBrace = "true", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| +- VariableDeclarationStatements[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| | +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "false", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
| | +- VariableDeclaration[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "s", @Namespace = "", @RealLoc = "true", @Type = "String"]
| | +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "BillingCity", @Namespace = "", @RealLoc = "true"]
| | | +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "LOAD", @SObjectType = "false", @SafeNav = "true"]
| | | +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "Account", @Namespace = "", @RealLoc = "true"]
| | | +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Image = "contact", @Namespace = "", @RealLoc = "true", @ReferenceType = "LOAD", @SObjectType = "false", @SafeNav = "false"]
| | +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "s", @Namespace = "", @RealLoc = "true"]
| | +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
| +- ReturnStatement[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "Name", @Namespace = "", @RealLoc = "true"]
| +- ReferenceExpression[@ApexVersion = "54.0", @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = "false", @ReferenceType = "LOAD", @SObjectType = "false", @SafeNav = "true"]
| +- SoqlExpression[@ApexVersion = "54.0", @CanonicalQuery = "SELECT Name FROM Account WHERE Id = :tmpVar1", @DefiningType = "Foo", @Namespace = "", @Query = "SELECT Name FROM Account WHERE Id = :accId", @RealLoc = "true"]
| +- BindExpressions[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "true"]
| +- VariableExpression[@ApexVersion = "54.0", @DefiningType = "Foo", @Image = "accId", @Namespace = "", @RealLoc = "true"]
| +- EmptyReferenceExpression[@ApexVersion = "54.0", @DefiningType = null, @Namespace = null, @RealLoc = "false"]
+- Method[@ApexVersion = "54.0", @Arity = "0", @CanonicalName = "<clinit>", @Constructor = "false", @DefiningType = "Foo", @Image = "<clinit>", @Namespace = "", @RealLoc = "false", @ReturnType = "void", @Synthetic = "true"]
| +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "false", @InheritedSharing = "false", @Modifiers = "8", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "true", @Static = "true", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
+- Method[@ApexVersion = "54.0", @Arity = "0", @CanonicalName = "clone", @Constructor = "false", @DefiningType = "Foo", @Image = "clone", @Namespace = "", @RealLoc = "false", @ReturnType = "Object", @Synthetic = "true"]
| +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "true", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "false", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
+- UserClassMethods[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "false"]
| +- Method[@ApexVersion = "54.0", @Arity = "0", @CanonicalName = "<init>", @Constructor = "true", @DefiningType = "Foo", @Image = "<init>", @Namespace = "", @RealLoc = "false", @ReturnType = "void", @Synthetic = "true"]
| +- ModifierNode[@Abstract = "false", @ApexVersion = "54.0", @DefiningType = "Foo", @DeprecatedTestMethod = "false", @Final = "false", @Global = "true", @InheritedSharing = "false", @Modifiers = "0", @Namespace = "", @Override = "false", @Private = "false", @Protected = "false", @Public = "false", @RealLoc = "true", @Static = "false", @Test = "false", @TestOrTestSetup = "false", @Transient = "false", @Virtual = "false", @WebService = "false", @WithSharing = "false", @WithoutSharing = "false"]
+- BridgeMethodCreator[@ApexVersion = "54.0", @DefiningType = "Foo", @Namespace = "", @RealLoc = "false"]
+- ApexFile[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
+- UserClass[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "Foo", @Namespace = "", @RealLoc = true, @SimpleName = "Foo", @SuperClassName = ""]
+- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- Field[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "x", @Name = "x", @Namespace = "", @RealLoc = true, @Type = "Integer", @Value = null]
| +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- Field[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "profileUrl", @Name = "profileUrl", @Namespace = "", @RealLoc = true, @Type = "String", @Value = null]
| +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- FieldDeclarationStatements[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true, @TypeName = "Integer"]
| +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- FieldDeclaration[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "anIntegerField", @Name = "anIntegerField", @Namespace = "", @RealLoc = true]
| +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "anIntegerField", @Namespace = "", @RealLoc = true]
| | +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.LOAD, @SObjectType = false, @SafeNav = true]
| | +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "anObject", @Namespace = "", @RealLoc = true]
| | +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
| +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "x", @Namespace = "", @RealLoc = true]
| +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
+- FieldDeclarationStatements[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true, @TypeName = "String"]
| +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- FieldDeclaration[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "profileUrl", @Name = "profileUrl", @Namespace = "", @RealLoc = true]
| +- MethodCallExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @FullMethodName = "toExternalForm", @InputParametersSize = 0, @MethodName = "toExternalForm", @Namespace = "", @RealLoc = true]
| | +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = true]
| | +- MethodCallExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @FullMethodName = "user.getProfileUrl", @InputParametersSize = 0, @MethodName = "getProfileUrl", @Namespace = "", @RealLoc = true]
| | +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Image = "user", @Namespace = "", @RealLoc = true, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
| +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "profileUrl", @Namespace = "", @RealLoc = true]
| +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
+- Method[@ApexVersion = 54.0, @Arity = 1, @CanonicalName = "bar1", @Constructor = false, @DefiningType = "Foo", @Image = "bar1", @Namespace = "", @RealLoc = true, @ReturnType = "void", @Synthetic = false]
| +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- Parameter[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "a", @Namespace = "", @RealLoc = true, @Type = "Object"]
| | +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- BlockStatement[@ApexVersion = 54.0, @CurlyBrace = true, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| +- ExpressionStatement[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| | +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "b", @Namespace = "", @RealLoc = true]
| | +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.LOAD, @SObjectType = false, @SafeNav = true]
| | +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "a", @Namespace = "", @RealLoc = true]
| | +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
| +- ExpressionStatement[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| +- MethodCallExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @FullMethodName = "c1", @InputParametersSize = 0, @MethodName = "c1", @Namespace = "", @RealLoc = true]
| +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = true]
| +- CastExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "b1", @Namespace = "", @RealLoc = true]
| +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.LOAD, @SObjectType = false, @SafeNav = true]
| +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "a1", @Namespace = "", @RealLoc = true]
| +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
+- Method[@ApexVersion = 54.0, @Arity = 2, @CanonicalName = "bar2", @Constructor = false, @DefiningType = "Foo", @Image = "bar2", @Namespace = "", @RealLoc = true, @ReturnType = "void", @Synthetic = false]
| +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- Parameter[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "a", @Namespace = "", @RealLoc = true, @Type = "List<Object>"]
| | +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- Parameter[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "x", @Namespace = "", @RealLoc = true, @Type = "int"]
| | +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- BlockStatement[@ApexVersion = 54.0, @CurlyBrace = true, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| +- ExpressionStatement[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| | +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "aField", @Namespace = "", @RealLoc = true]
| | +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.LOAD, @SObjectType = false, @SafeNav = false]
| | +- MethodCallExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @FullMethodName = "aMethod", @InputParametersSize = 0, @MethodName = "aMethod", @Namespace = "", @RealLoc = true]
| | +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = true]
| | +- ArrayLoadExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| | +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "a", @Namespace = "", @RealLoc = true]
| | | +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
| | +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "x", @Namespace = "", @RealLoc = true]
| | +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
| +- ExpressionStatement[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "aField", @Namespace = "", @RealLoc = true]
| +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.LOAD, @SObjectType = false, @SafeNav = true]
| +- MethodCallExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @FullMethodName = "aMethod", @InputParametersSize = 0, @MethodName = "aMethod", @Namespace = "", @RealLoc = true]
| +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.METHOD, @SObjectType = false, @SafeNav = false]
| +- ArrayLoadExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "a", @Namespace = "", @RealLoc = true]
| | +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
| +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "x", @Namespace = "", @RealLoc = true]
| +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
+- Method[@ApexVersion = 54.0, @Arity = 1, @CanonicalName = "getName", @Constructor = false, @DefiningType = "Foo", @Image = "getName", @Namespace = "", @RealLoc = true, @ReturnType = "String", @Synthetic = false]
| +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 1, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = true, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- Parameter[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "accId", @Namespace = "", @RealLoc = true, @Type = "int"]
| | +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| +- BlockStatement[@ApexVersion = 54.0, @CurlyBrace = true, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| +- VariableDeclarationStatements[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| | +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
| | +- VariableDeclaration[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "s", @Namespace = "", @RealLoc = true, @Type = "String"]
| | +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "BillingCity", @Namespace = "", @RealLoc = true]
| | | +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.LOAD, @SObjectType = false, @SafeNav = true]
| | | +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "Account", @Namespace = "", @RealLoc = true]
| | | +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Image = "contact", @Namespace = "", @RealLoc = true, @ReferenceType = ReferenceType.LOAD, @SObjectType = false, @SafeNav = false]
| | +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "s", @Namespace = "", @RealLoc = true]
| | +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
| +- ReturnStatement[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "Name", @Namespace = "", @RealLoc = true]
| +- ReferenceExpression[@ApexVersion = 54.0, @Context = null, @DefiningType = "Foo", @Namespace = "", @RealLoc = false, @ReferenceType = ReferenceType.LOAD, @SObjectType = false, @SafeNav = true]
| +- SoqlExpression[@ApexVersion = 54.0, @CanonicalQuery = "SELECT Name FROM Account WHERE Id = :tmpVar1", @DefiningType = "Foo", @Namespace = "", @Query = "SELECT Name FROM Account WHERE Id = :accId", @RealLoc = true]
| +- BindExpressions[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = true]
| +- VariableExpression[@ApexVersion = 54.0, @DefiningType = "Foo", @Image = "accId", @Namespace = "", @RealLoc = true]
| +- EmptyReferenceExpression[@ApexVersion = 54.0, @DefiningType = null, @Namespace = null, @RealLoc = false]
+- Method[@ApexVersion = 54.0, @Arity = 0, @CanonicalName = "<clinit>", @Constructor = false, @DefiningType = "Foo", @Image = "<clinit>", @Namespace = "", @RealLoc = false, @ReturnType = "void", @Synthetic = true]
| +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = false, @InheritedSharing = false, @Modifiers = 8, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = true, @Static = true, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- Method[@ApexVersion = 54.0, @Arity = 0, @CanonicalName = "clone", @Constructor = false, @DefiningType = "Foo", @Image = "clone", @Namespace = "", @RealLoc = false, @ReturnType = "Object", @Synthetic = true]
| +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = true, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = false, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- UserClassMethods[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = false]
| +- Method[@ApexVersion = 54.0, @Arity = 0, @CanonicalName = "<init>", @Constructor = true, @DefiningType = "Foo", @Image = "<init>", @Namespace = "", @RealLoc = false, @ReturnType = "void", @Synthetic = true]
| +- ModifierNode[@Abstract = false, @ApexVersion = 54.0, @DefiningType = "Foo", @DeprecatedTestMethod = false, @Final = false, @Global = true, @InheritedSharing = false, @Modifiers = 0, @Namespace = "", @Override = false, @Private = false, @Protected = false, @Public = false, @RealLoc = true, @Static = false, @Test = false, @TestOrTestSetup = false, @Transient = false, @Virtual = false, @WebService = false, @WithSharing = false, @WithoutSharing = false]
+- BridgeMethodCreator[@ApexVersion = 54.0, @DefiningType = "Foo", @Namespace = "", @RealLoc = false]

View File

@ -139,5 +139,10 @@
<artifactId>system-rules</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>me.tongfei</groupId>
<artifactId>progressbar</artifactId>
<version>0.9.3</version>
</dependency>
</dependencies>
</project>

View File

@ -13,7 +13,10 @@ import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.stream.Collectors;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
@ -32,7 +35,6 @@ import net.sourceforge.pmd.lang.document.TextFile;
import net.sourceforge.pmd.renderers.Renderer;
import net.sourceforge.pmd.reporting.ReportStats;
import net.sourceforge.pmd.reporting.ReportStatsListener;
import net.sourceforge.pmd.util.CollectionUtil;
import net.sourceforge.pmd.util.datasource.DataSource;
import net.sourceforge.pmd.util.log.MessageReporter;
import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter;
@ -124,7 +126,6 @@ public final class PMD {
* @return Report in which violations are accumulated
*
* @throws Exception If there was a problem when opening or closing the renderers
*
* @deprecated Use {@link PmdAnalysis}
*/
@Deprecated
@ -138,9 +139,11 @@ public final class PMD {
pmd.addRenderers(renderers);
@SuppressWarnings("PMD.CloseResource")
GlobalReportBuilderListener reportBuilder = new GlobalReportBuilderListener();
List<TextFile> textFiles = CollectionUtil.map(files, ds -> TextFile.dataSourceCompat(ds, configuration));
textFiles.sort(Comparator.comparing(TextFile::getPathId));
pmd.performAnalysisImpl(listOf(reportBuilder), textFiles);
List<TextFile> sortedFiles = files.stream()
.map(ds -> TextFile.dataSourceCompat(ds, configuration))
.sorted(Comparator.comparing(TextFile::getPathId))
.collect(Collectors.toList());
pmd.performAnalysisImpl(listOf(reportBuilder), sortedFiles);
return reportBuilder.getResult();
}
}
@ -190,7 +193,12 @@ public final class PMD {
System.err.println(CliMessages.runWithHelpFlagMessage());
return StatusCode.ERROR;
}
return runPmd(parseResult.toConfiguration());
PMDConfiguration configuration = Objects.requireNonNull(parseResult.toConfiguration());
MessageReporter pmdReporter = setupMessageReporter(configuration);
configuration.setReporter(pmdReporter);
return runPmd(configuration);
}
private static void printErrorDetected(int errors) {
@ -214,28 +222,11 @@ public final class PMD {
TimeTracker.startGlobalTracking();
}
// only reconfigure logging, if debug flag was used on command line
// otherwise just use whatever is in conf/simplelogger.properties which happens automatically
if (configuration.isDebug()) {
Slf4jSimpleConfiguration.reconfigureDefaultLogLevel(Level.TRACE);
// need to reload the logger with the new configuration
log = LoggerFactory.getLogger(PMD.class);
}
// create a top-level reporter
// TODO CLI errors should also be reported through this
// TODO this should not use the logger as backend, otherwise without
// slf4j implementation binding, errors are entirely ignored.
MessageReporter pmdReporter = new SimpleMessageReporter(log);
// always install java.util.logging to slf4j bridge
Slf4jSimpleConfiguration.installJulBridge();
// logging, mostly for testing purposes
Level defaultLogLevel = Slf4jSimpleConfiguration.getDefaultLogLevel();
log.info("Log level is at {}", defaultLogLevel);
MessageReporter pmdReporter = configuration.getReporter();
try {
PmdAnalysis pmd;
try {
pmd = PmdAnalysis.create(configuration, pmdReporter);
pmd = PmdAnalysis.create(configuration);
} catch (Exception e) {
pmdReporter.errorEx("Could not initialize analysis", e);
return StatusCode.ERROR;
@ -264,6 +255,27 @@ public final class PMD {
}
}
private static @NonNull MessageReporter setupMessageReporter(PMDConfiguration configuration) {
// only reconfigure logging, if debug flag was used on command line
// otherwise just use whatever is in conf/simplelogger.properties which happens automatically
if (configuration.isDebug()) {
Slf4jSimpleConfiguration.reconfigureDefaultLogLevel(Level.TRACE);
// need to reload the logger with the new configuration
log = LoggerFactory.getLogger(PMD.class);
}
// create a top-level reporter
// TODO CLI errors should also be reported through this
// TODO this should not use the logger as backend, otherwise without
// slf4j implementation binding, errors are entirely ignored.
MessageReporter pmdReporter = new SimpleMessageReporter(log);
// always install java.util.logging to slf4j bridge
Slf4jSimpleConfiguration.installJulBridge();
// logging, mostly for testing purposes
Level defaultLogLevel = Slf4jSimpleConfiguration.getDefaultLogLevel();
log.info("Log level is at {}", defaultLogLevel);
return pmdReporter;
}
private static void finishBenchmarker(PMDConfiguration configuration) {
if (configuration.isBenchmark()) {
final TimingReport timingReport = TimeTracker.stopGlobalTracking();

View File

@ -16,6 +16,7 @@ import java.util.Properties;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.slf4j.LoggerFactory;
import net.sourceforge.pmd.annotation.DeprecatedUntil700;
import net.sourceforge.pmd.cache.AnalysisCache;
@ -29,6 +30,8 @@ import net.sourceforge.pmd.lang.LanguageVersionDiscoverer;
import net.sourceforge.pmd.renderers.Renderer;
import net.sourceforge.pmd.renderers.RendererFactory;
import net.sourceforge.pmd.util.ClasspathClassLoader;
import net.sourceforge.pmd.util.log.MessageReporter;
import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter;
/**
* This class contains the details for the runtime configuration of a PMD run.
@ -102,6 +105,7 @@ public class PMDConfiguration extends AbstractConfiguration {
private ClassLoader classLoader = getClass().getClassLoader();
private LanguageVersionDiscoverer languageVersionDiscoverer = new LanguageVersionDiscoverer();
private LanguageVersion forceLanguageVersion;
private MessageReporter reporter = new SimpleMessageReporter(LoggerFactory.getLogger(PMD.class));
// Rule and source file options
private List<String> ruleSets = new ArrayList<>();
@ -124,6 +128,7 @@ public class PMDConfiguration extends AbstractConfiguration {
private boolean benchmark;
private AnalysisCache analysisCache = new NoopAnalysisCache();
private boolean ignoreIncrementalAnalysis;
private boolean progressBar = false;
/**
* Get the suppress marker. This is the source level marker used to indicate
@ -248,6 +253,25 @@ public class PMDConfiguration extends AbstractConfiguration {
}
}
/**
* Returns the message reporter that is to be used while running
* the analysis.
*/
public @NonNull MessageReporter getReporter() {
return reporter;
}
/**
* Sets the message reporter that is to be used while running
* the analysis.
*
* @param reporter A non-null message reporter
*/
public void setReporter(@NonNull MessageReporter reporter) {
AssertionUtil.requireParamNotNull("reporter", reporter);
this.reporter = reporter;
}
/**
* Get the LanguageVersionDiscoverer, used to determine the LanguageVersion
* of a source file.
@ -340,7 +364,7 @@ public class PMDConfiguration extends AbstractConfiguration {
if (languageVersion == null) {
// For compatibility with older code that does not always pass in
// a correct filename.
languageVersion = languageVersionDiscoverer.getDefaultLanguageVersion(LanguageRegistry.getLanguage("Java"));
languageVersion = languageVersionDiscoverer.getDefaultLanguageVersion(LanguageRegistry.getDefaultLanguage());
}
return languageVersion;
}
@ -800,4 +824,25 @@ public class PMDConfiguration extends AbstractConfiguration {
return ignoreIncrementalAnalysis;
}
/**
* Sets whether to indicate analysis progress in command line output.
*
* @param progressBar Whether to enable progress bar indicator in CLI
*/
public void setProgressBar(boolean progressBar) {
this.progressBar = progressBar;
}
/**
* Returns whether progress bar indicator should be used. The default
* is false.
*
* @return {@code true} if progress bar indicator is enabled
*/
public boolean isProgressBar() {
return progressBar;
}
}

View File

@ -18,11 +18,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sourceforge.pmd.Report.GlobalReportBuilderListener;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.benchmark.TimeTracker;
import net.sourceforge.pmd.benchmark.TimedOperation;
import net.sourceforge.pmd.benchmark.TimedOperationCategory;
import net.sourceforge.pmd.cache.AnalysisCacheListener;
import net.sourceforge.pmd.cli.internal.ProgressBarListener;
import net.sourceforge.pmd.internal.util.AssertionUtil;
import net.sourceforge.pmd.internal.util.FileCollectionUtil;
import net.sourceforge.pmd.lang.Language;
@ -36,7 +36,6 @@ import net.sourceforge.pmd.reporting.GlobalAnalysisListener;
import net.sourceforge.pmd.util.ClasspathClassLoader;
import net.sourceforge.pmd.util.IOUtil;
import net.sourceforge.pmd.util.log.MessageReporter;
import net.sourceforge.pmd.util.log.internal.SimpleMessageReporter;
/**
* Main programmatic API of PMD. Create and configure a {@link PMDConfiguration},
@ -87,9 +86,9 @@ public final class PmdAnalysis implements AutoCloseable {
* the file collector ({@link #files()}), but more can be added
* programmatically using the file collector.
*/
private PmdAnalysis(PMDConfiguration config, MessageReporter reporter) {
private PmdAnalysis(PMDConfiguration config) {
this.configuration = config;
this.reporter = reporter;
this.reporter = config.getReporter();
this.collector = FileCollector.newCollector(
config.getLanguageVersionDiscoverer(),
reporter
@ -110,15 +109,7 @@ public final class PmdAnalysis implements AutoCloseable {
* </ul>
*/
public static PmdAnalysis create(PMDConfiguration config) {
return create(
config,
new SimpleMessageReporter(LoggerFactory.getLogger(PmdAnalysis.class))
);
}
@InternalApi
static PmdAnalysis create(PMDConfiguration config, MessageReporter reporter) {
PmdAnalysis pmd = new PmdAnalysis(config, reporter);
PmdAnalysis pmd = new PmdAnalysis(config);
// note: do not filter files by language
// they could be ignored later. The problem is if you call
@ -286,7 +277,14 @@ public final class PmdAnalysis implements AutoCloseable {
GlobalAnalysisListener listener;
try {
@SuppressWarnings("PMD.CloseResource") AnalysisCacheListener cacheListener = new AnalysisCacheListener(configuration.getAnalysisCache(), rulesets, configuration.getClassLoader());
listener = GlobalAnalysisListener.tee(listOf(createComposedRendererListener(renderers), GlobalAnalysisListener.tee(listeners), GlobalAnalysisListener.tee(extraListeners), cacheListener));
if (configuration.isProgressBar()) {
@SuppressWarnings("PMD.CloseResource") ProgressBarListener progressBarListener = new ProgressBarListener(textFiles.size(), System.out::print);
addListener(progressBarListener);
}
listener = GlobalAnalysisListener.tee(listOf(createComposedRendererListener(renderers),
GlobalAnalysisListener.tee(listeners),
GlobalAnalysisListener.tee(extraListeners),
cacheListener));
} catch (Exception e) {
reporter.errorEx("Exception while initializing analysis listeners", e);
throw new RuntimeException("Exception while initializing analysis listeners", e);

View File

@ -13,8 +13,10 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import net.sourceforge.pmd.annotation.DeprecatedUntil700;
import net.sourceforge.pmd.annotation.Experimental;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.lang.document.TextFile;
import net.sourceforge.pmd.renderers.AbstractAccumulatingRenderer;
@ -30,6 +32,15 @@ import net.sourceforge.pmd.util.BaseResultProducingCloseable;
* <p>A report may be created by a {@link GlobalReportBuilderListener} that you
* use as the {@linkplain GlobalAnalysisListener} in {@link PmdAnalysis#performAnalysisAndCollectReport() PMD's entry point}.
* You can also create one manually with {@link #buildReport(Consumer)}.
*
* <p>For special use cases, like filtering the report after PMD analysis and
* before rendering the report, some transformation operations are provided:
* <ul>
* <li>{@link #filterViolations(Predicate)}</li>
* <li>{@link #union(Report)}</li>
* </ul>
* These methods create a new {@link Report} rather than modifying their receiver.
* </p>
*/
public final class Report {
// todo move to package reporting
@ -352,4 +363,57 @@ public final class Report {
return report;
}
}
/**
* Creates a new report taking all the information from this report,
* but filtering the violations.
*
* @param filter when true, the violation will be kept.
* @return copy of this report
*/
@Experimental
public Report filterViolations(Predicate<RuleViolation> filter) {
Report copy = new Report();
for (RuleViolation violation : violations) {
if (filter.test(violation)) {
copy.addRuleViolation(violation);
}
}
copy.suppressedRuleViolations.addAll(suppressedRuleViolations);
copy.errors.addAll(errors);
copy.configErrors.addAll(configErrors);
return copy;
}
/**
* Creates a new report by combining this report with another report.
* This is similar to {@link #merge(Report)}, but instead a new report
* is created. The lowest start time and greatest end time are kept in the copy.
*
* @param other the other report to combine
* @return
*/
@Experimental
public Report union(Report other) {
Report copy = new Report();
for (RuleViolation violation : violations) {
copy.addRuleViolation(violation);
}
for (RuleViolation violation : other.violations) {
copy.addRuleViolation(violation);
}
copy.suppressedRuleViolations.addAll(suppressedRuleViolations);
copy.suppressedRuleViolations.addAll(other.suppressedRuleViolations);
copy.errors.addAll(errors);
copy.errors.addAll(other.errors);
copy.configErrors.addAll(configErrors);
copy.configErrors.addAll(other.configErrors);
return copy;
}
}

View File

@ -14,6 +14,7 @@ import net.sourceforge.pmd.Report.SuppressedViolation;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.document.FileLocation;
import net.sourceforge.pmd.lang.document.TextRange2d;
import net.sourceforge.pmd.lang.rule.AbstractRule;
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
import net.sourceforge.pmd.processor.AbstractPMDProcessor;
@ -131,7 +132,7 @@ public final class RuleContext {
FileLocation location = node.getReportLocation();
if (beginLine != -1 && endLine != -1) {
location = FileLocation.range(location.getFileName(), beginLine, 1, endLine, 1);
location = FileLocation.range(location.getFileName(), TextRange2d.range2d(beginLine, 1, endLine, 1));
}
RuleViolation violation = fact.createViolation(rule, node, location, makeMessage(message, formatArgs));

View File

@ -71,7 +71,7 @@ public interface RuleViolation {
* @return Begin line number.
*/
default int getBeginLine() {
return getLocation().getBeginLine();
return getLocation().getStartPos().getLine();
}
/**
@ -81,7 +81,7 @@ public interface RuleViolation {
* @return Begin column number.
*/
default int getBeginColumn() {
return getLocation().getBeginColumn();
return getLocation().getStartPos().getColumn();
}
/**
@ -91,7 +91,7 @@ public interface RuleViolation {
* @return End line number.
*/
default int getEndLine() {
return getLocation().getEndLine();
return getLocation().getEndPos().getLine();
}
/**
@ -101,7 +101,7 @@ public interface RuleViolation {
* @return End column number.
*/
default int getEndColumn() {
return getLocation().getEndColumn();
return getLocation().getEndPos().getColumn();
}
/**

View File

@ -110,7 +110,6 @@ public class Formatter {
}
renderer = createRenderer();
renderer.setWriter(writer);
renderer.start();
} catch (IOException ioe) {
throw new BuildException(ioe.getMessage(), ioe);
}

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