forked from phoedos/pmd
Merge branch '7.0.x' into pmd7-merge-xml-rule
This commit is contained in:
commit
b0ce80350f
@ -6566,6 +6566,15 @@
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "btjiong",
|
||||
"name": "Bailey Tjiong",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15816011?v=4",
|
||||
"profile": "https://github.com/btjiong",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
@ -40,10 +40,6 @@ mvn dependency:build-classpath -DincludeScope=test -Dmdep.outputFile=classpath.t
|
||||
<exclude-pattern>.*/build/generated-sources/.*</exclude-pattern>
|
||||
|
||||
<build-command><![CDATA[#!/usr/bin/env bash
|
||||
if test -e classpath.txt; then
|
||||
exit
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
# Make sure to use java11. This is already installed by build.sh
|
||||
@ -133,6 +129,11 @@ index 6021fa574d..15d29ed699 100644
|
||||
EOF
|
||||
) | patch --strip=1
|
||||
|
||||
## Skip gradle execution
|
||||
if test -e classpath.txt; then
|
||||
exit
|
||||
fi
|
||||
|
||||
./gradlew --console=plain --build-cache --no-daemon --max-workers=4 build testClasses -x test -x javadoc -x api -x asciidoctor -x asciidoctorPdf
|
||||
./gradlew --console=plain --build-cache --no-daemon --max-workers=4 createSquishClasspath -q > classpath.txt
|
||||
]]></build-command>
|
||||
|
2
.mvn/wrapper/maven-wrapper.properties
vendored
2
.mvn/wrapper/maven-wrapper.properties
vendored
@ -14,5 +14,5 @@
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
|
||||
|
@ -1,12 +1,30 @@
|
||||
<footer>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 footer">
|
||||
<p class="float-right"><img src="{{ "images/logo/pmd-logo-70px.png" }}" alt="PMD logo"/></p>
|
||||
<p>
|
||||
©{{ site.time | date: "%Y" }} {{site.company_name}}. All rights reserved. <br />
|
||||
{% if page.last_updated %}<span>Page last updated:</span> {{page.last_updated}}<br/>{% endif %}
|
||||
Site last generated: {{ site.time | date: "%b %-d, %Y" }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% if site.github_editme_path and page.editmepath != false %}
|
||||
<hr />
|
||||
<div>
|
||||
This documentation is written in markdown. <br />
|
||||
If there is something missing or can be improved, edit this page on
|
||||
github and create a PR:
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://github.com/{{site.github_editme_path}}{{editmepath}}"
|
||||
role="button"
|
||||
><i class="fa fa-github fa-lg"></i> Edit on GitHub</a
|
||||
>
|
||||
</div>
|
||||
{% endif %}
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col-lg-12 footer">
|
||||
©{{ site.time | date: "%Y" }} {{site.company_name}}. All rights
|
||||
reserved. <br />
|
||||
{% if page.last_updated %}<span>Page last updated:</span>
|
||||
{{page.last_updated}}<br />{% endif %} Site last generated: {{
|
||||
site.time | date: "%b %-d, %Y" }} <br />
|
||||
<p>
|
||||
<img src="{{ "images/logo/pmd-logo-70px.png" }}" alt="PMD
|
||||
logo"/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
23
docs/_includes/header.html
Normal file
23
docs/_includes/header.html
Normal file
@ -0,0 +1,23 @@
|
||||
<header>
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<a href="./" role="button"
|
||||
><i class="fa fa-home fa-lg"></i
|
||||
></a>
|
||||
» {{page.title}} {% if site.github_editme_path %} {% assign
|
||||
editmepath = page.path %} {% if page.editmepath %} {% assign
|
||||
editmepath = page.editmepath %} {% endif %}{% unless page.editmepath
|
||||
== false %}
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://github.com/{{site.github_editme_path}}{{editmepath}}"
|
||||
class="float-right"
|
||||
role="button"
|
||||
><i class="fa fa-github fa-lg"></i> Edit on GitHub</a
|
||||
>
|
||||
{% endunless %} {% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
</header>
|
@ -1,5 +0,0 @@
|
||||
{% comment %}
|
||||
Note: The content of the div-element is filled by javascript. See customscripts.js.
|
||||
{% endcomment %}
|
||||
|
||||
<div id="toc"></div>
|
@ -36,7 +36,7 @@
|
||||
{% unless page.toc == false %}
|
||||
<!-- Sticky TOC column -->
|
||||
<div class="toc-col">
|
||||
{% include toc.html %}
|
||||
<div id="toc"></div>
|
||||
</div>
|
||||
{% endunless %}
|
||||
<!-- /.toc-container-wrapper -->
|
||||
|
@ -2,31 +2,19 @@
|
||||
layout: default
|
||||
---
|
||||
|
||||
{% include header.html %}
|
||||
|
||||
<div class="post-header">
|
||||
<h1 class="post-title-main">{{ page.title }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="post-content">
|
||||
<div class="post-content" {% if site.github_editme_path and page.editmepath != false %}data-github-edit-url="https://github.com/{{site.github_editme_path}}{{editmepath}}"{% endif %}>
|
||||
|
||||
{% if page.summary %}
|
||||
<div class="summary">{{page.summary}}</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="inline-toc"><!-- empty, move TOC here when screen size too small --></div>
|
||||
|
||||
|
||||
{% if site.github_editme_path %}
|
||||
|
||||
{% assign editmepath = page.path %}
|
||||
{% if page.editmepath %}
|
||||
{% assign editmepath = page.editmepath %}
|
||||
{% endif %}
|
||||
{% unless page.editmepath == false %}
|
||||
<a target="_blank" href="https://github.com/{{site.github_editme_path}}{{editmepath}}" class="btn btn-outline-secondary githubEditButton" role="button"><i class="fab fa-github fa-lg"></i> Edit me</a>
|
||||
{% endunless %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{{content}}
|
||||
|
||||
<div class="tags">
|
||||
@ -43,6 +31,5 @@ layout: default
|
||||
|
||||
</div>
|
||||
|
||||
{{site.data.alerts.hr_shaded}}
|
||||
|
||||
{% include footer.html %}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,10 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
header {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
details {
|
||||
border-radius: 3px;
|
||||
background: #EEE;
|
||||
|
@ -1,14 +1,21 @@
|
||||
|
||||
// Detect small devices and move the TOC in line
|
||||
function moveToc(){
|
||||
if(window.innerWidth < 1350){
|
||||
$( "#toc" ).detach().appendTo("#inline-toc").removeClass("position-fixed");
|
||||
$( '#toc' ).detach().appendTo('#inline-toc').removeClass('position-fixed');
|
||||
} else {
|
||||
$( "#toc" ).detach().appendTo(".toc-col").addClass("position-fixed");
|
||||
$( '#toc' ).detach().appendTo('.toc-col').addClass('position-fixed');
|
||||
}
|
||||
}
|
||||
|
||||
$( document ).ready(function() {
|
||||
$(document).ready(function () {
|
||||
// This handles the automatic toc. Use ## for subheads to auto-generate the on-page minitoc.
|
||||
// If you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc.
|
||||
$('#toc').toc({
|
||||
minimumHeaders: 0,
|
||||
listType: 'ul',
|
||||
showSpeed: 0,
|
||||
headers: 'h2,h3,h4',
|
||||
});
|
||||
|
||||
$('#mysidebar').height($(".nav").height());
|
||||
|
||||
@ -18,18 +25,31 @@ $( document ).ready(function() {
|
||||
var h = $(window).height();
|
||||
//console.log (h);
|
||||
if (h > 600) {
|
||||
$( "#mysidebar" ).attr("class", "nav position-fixed");
|
||||
$( '#mysidebar' ).attr('class', 'nav position-fixed');
|
||||
}
|
||||
|
||||
// activate tooltips. although this is a bootstrap js function, it must be activated this way in your theme.
|
||||
$('[data-toggle="tooltip"]').tooltip({
|
||||
placement : 'top'
|
||||
placement: 'top',
|
||||
});
|
||||
|
||||
/**
|
||||
* AnchorJS
|
||||
*/
|
||||
anchors.add('h2,h3,h4,h5');
|
||||
|
||||
// Add an "Edit on GitHub" button to each header (except h1)
|
||||
let url = $('div.post-content').data('githubEditUrl');
|
||||
if ( url !== undefined ) {
|
||||
$('div.post-content')
|
||||
.find(':header:not(h1)')
|
||||
.append(
|
||||
' <a class="edit-header" target="_blank" href=' +
|
||||
url +
|
||||
' role="button">✏️️</a>'
|
||||
);
|
||||
}
|
||||
|
||||
// Check if TOC needs to be moved on page load
|
||||
moveToc();
|
||||
|
||||
@ -37,10 +57,10 @@ $( document ).ready(function() {
|
||||
// when you're viewing a page.
|
||||
// Note: the class needs to be added before navgoco is initialized. Navgoco uses then this information
|
||||
// to expand the menus.
|
||||
$("li.active").parents('li').toggleClass("active");
|
||||
$( 'li.active' ).parents('li').toggleClass('active');
|
||||
|
||||
// Initialize navgoco with default options
|
||||
$("#mysidebar").navgoco({
|
||||
$( '#mysidebar' ).navgoco({
|
||||
caretHtml: '',
|
||||
accordion: true,
|
||||
openClass: 'active',
|
||||
@ -51,10 +71,6 @@ $( document ).ready(function() {
|
||||
}
|
||||
});
|
||||
|
||||
// This handles the automatic toc. Use ## for subheads to auto-generate the on-page minitoc.
|
||||
// If you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc.
|
||||
$('#toc').toc({ minimumHeaders: 0, listType: 'ul', showSpeed: 0, headers: 'h2,h3,h4' });
|
||||
|
||||
// Initialize jekyll search in topnav.
|
||||
SimpleJekyllSearch.init({
|
||||
searchInput: document.getElementById('search-input'),
|
||||
@ -85,4 +101,6 @@ $( document ).ready(function() {
|
||||
});
|
||||
|
||||
// Check if TOC needs to be moved on window resizing
|
||||
$(window).resize(function () {moveToc();});
|
||||
$(window).resize(function () {
|
||||
moveToc();
|
||||
});
|
||||
|
@ -5,38 +5,38 @@
|
||||
$('a[data-toggle="pill"], a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
|
||||
var tabId, json, parentId, tabsState;
|
||||
|
||||
tabsState = localStorage.getItem("tabs-state");
|
||||
tabsState = localStorage.getItem('tabs-state');
|
||||
json = JSON.parse(tabsState || "{}");
|
||||
parentId = $(e.target).parents("ul.nav.nav-pills, ul.nav.nav-tabs").attr("id");
|
||||
parentId = $(e.target).parents('ul.nav.nav-pills, ul.nav.nav-tabs').attr('id');
|
||||
tabId = $(e.target).attr('id');
|
||||
json[parentId] = tabId;
|
||||
|
||||
return localStorage.setItem("tabs-state", JSON.stringify(json));
|
||||
return localStorage.setItem('tabs-state', JSON.stringify(json));
|
||||
});
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var json, tabsState;
|
||||
tabsState = localStorage.getItem("tabs-state");
|
||||
json = JSON.parse(tabsState || "{}");
|
||||
tabsState = localStorage.getItem('tabs-state');
|
||||
json = JSON.parse(tabsState || '{}');
|
||||
|
||||
$.each(json, function(containerId, tabId) {
|
||||
if (containerId && containerId !== "undefined" && tabId && tabId !== "undefined"
|
||||
if (containerId && containerId !== 'undefined' && tabId && tabId !== 'undefined'
|
||||
&& tabId.indexOf('#') !== 0) {
|
||||
$("#" + tabId).tab('show');
|
||||
$('#' + tabId).tab('show');
|
||||
}
|
||||
});
|
||||
|
||||
$("ul.nav.nav-pills, ul.nav.nav-tabs").each(function() {
|
||||
$('ul.nav.nav-pills, ul.nav.nav-tabs').each(function() {
|
||||
var $this = $(this);
|
||||
if (!json[$this.attr("id")]) {
|
||||
return $this.find("a[data-toggle=tab]:first, a[data-toggle=pill]:first").tab("show");
|
||||
if (!json[$this.attr('id')]) {
|
||||
return $this.find('a[data-toggle=tab]:first, a[data-toggle=pill]:first').tab('show');
|
||||
}
|
||||
});
|
||||
|
||||
// cleanup "undefined" entries
|
||||
delete json['undefined'];
|
||||
localStorage.setItem("tabs-state", JSON.stringify(json));
|
||||
localStorage.setItem('tabs-state', JSON.stringify(json));
|
||||
|
||||
registerTabEvent();
|
||||
});
|
||||
|
@ -84,9 +84,6 @@ Now the source and binary distribution zip files can be found in the folder `pmd
|
||||
|
||||
**Notes:**
|
||||
|
||||
* The rules that have already been written are specified in the `src/main/resources/rulesets/` directories of
|
||||
the specific languages, e.g. `pmd-java/src/main/resources/rulesets`.
|
||||
They’re also in the jar file that’s included with both the source and binary distributions.
|
||||
|
||||
A paucity of detail, I’m sure you’d agree. If you think this document can be improved,
|
||||
please post [here](http://sourceforge.net/p/pmd/discussion/188192) and let me know how. Thanks!
|
||||
- The rules that have already been written are specified in the `src/main/resources/category/` directories of
|
||||
the specific languages, e.g. `pmd-java/src/main/resources/category`.
|
||||
They’re also in the jar file that’s included with both the source and binary distributions.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,11 +56,14 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is
|
||||
|
||||
### Fixed Issues
|
||||
|
||||
* apex
|
||||
* [#3817](https://github.com/pmd/pmd/pull/3817): \[apex] Add designer bindings to display main attributes
|
||||
* apex-performance
|
||||
* [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe()
|
||||
* core
|
||||
* [#3299](https://github.com/pmd/pmd/issues/3299): \[core] Deprecate system properties of PMDCommandLineInterface
|
||||
* doc
|
||||
* [#2504](https://github.com/pmd/pmd/issues/2504): \[doc] Improve "Edit me on github" button
|
||||
* [#3812](https://github.com/pmd/pmd/issues/3812): \[doc] Documentation website table of contents broken on pages with many subheadings
|
||||
|
||||
### API Changes
|
||||
@ -84,6 +87,11 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is
|
||||
The whole class however was deprecated long ago already with 6.30.0. It is internal API and should
|
||||
not be used.
|
||||
|
||||
* In modelica, the rule classes {% jdoc modelica::lang.modelica.rule.AmbiguousResolutionRule %}
|
||||
and {% jdoc modelica::lang.modelica.rule.ConnectUsingNonConnector %} have been deprecated,
|
||||
since they didn't comply to the usual rule class naming conventions yet.
|
||||
The replacements are in the subpackage `bestpractices`.
|
||||
|
||||
#### Experimental APIs
|
||||
|
||||
* Together with the [new programmatic API](#new-programmatic-api) the interface
|
||||
@ -98,6 +106,7 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is
|
||||
### External Contributions
|
||||
|
||||
* [#3773](https://github.com/pmd/pmd/pull/3773): \[apex] EagerlyLoadedDescribeSObjectResult false positives with SObjectField.getDescribe() - [@filiprafalowicz](https://github.com/filiprafalowicz)
|
||||
* [#3811](https://github.com/pmd/pmd/pull/3811): \[doc] Improve "Edit me on github" button - [@btjiong](https://github.com/btjiong)
|
||||
* [#3836](https://github.com/pmd/pmd/pull/3836): \[doc] Make TOC scrollable when too many subheadings - [@JerritEic](https://github.com/JerritEic)
|
||||
|
||||
{% endtocmaker %}
|
||||
|
@ -11,6 +11,7 @@ import java.util.Set;
|
||||
import net.sourceforge.pmd.annotation.InternalApi;
|
||||
import net.sourceforge.pmd.lang.AbstractPmdLanguageVersionHandler;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ApexParser;
|
||||
import net.sourceforge.pmd.lang.apex.internal.ApexDesignerBindings;
|
||||
import net.sourceforge.pmd.lang.apex.metrics.ApexMetrics;
|
||||
import net.sourceforge.pmd.lang.apex.rule.internal.ApexRuleViolationFactory;
|
||||
import net.sourceforge.pmd.lang.ast.Parser;
|
||||
@ -18,6 +19,7 @@ import net.sourceforge.pmd.lang.metrics.LanguageMetricsProvider;
|
||||
import net.sourceforge.pmd.lang.metrics.Metric;
|
||||
import net.sourceforge.pmd.lang.rule.RuleViolationFactory;
|
||||
import net.sourceforge.pmd.properties.PropertySource;
|
||||
import net.sourceforge.pmd.util.designerbindings.DesignerBindings;
|
||||
|
||||
@InternalApi
|
||||
public class ApexHandler extends AbstractPmdLanguageVersionHandler {
|
||||
@ -46,6 +48,11 @@ public class ApexHandler extends AbstractPmdLanguageVersionHandler {
|
||||
return myMetricsProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DesignerBindings getDesignerBindings() {
|
||||
return ApexDesignerBindings.INSTANCE;
|
||||
}
|
||||
|
||||
private static final class ApexMetricsProvider implements LanguageMetricsProvider {
|
||||
|
||||
private final Set<Metric<?, ?>> metrics = setOf(
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.apex.internal;
|
||||
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclaration;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethod;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTMethodCallExpression;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTUserClass;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ApexNode;
|
||||
import net.sourceforge.pmd.lang.apex.ast.ApexParserVisitorAdapter;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.rule.xpath.Attribute;
|
||||
import net.sourceforge.pmd.util.designerbindings.DesignerBindings.DefaultDesignerBindings;
|
||||
|
||||
public class ApexDesignerBindings extends DefaultDesignerBindings {
|
||||
|
||||
public static final ApexDesignerBindings INSTANCE = new ApexDesignerBindings();
|
||||
|
||||
@Override
|
||||
public Attribute getMainAttribute(Node node) {
|
||||
if (node instanceof ApexNode) {
|
||||
Attribute attr = (Attribute) ((ApexNode<?>) node).jjtAccept(MainAttrVisitor.INSTANCE, null);
|
||||
if (attr != null) {
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
|
||||
return super.getMainAttribute(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeIconId getIcon(Node node) {
|
||||
if (node instanceof ASTFieldDeclaration) {
|
||||
return TreeIconId.FIELD;
|
||||
} else if (node instanceof ASTUserClass) {
|
||||
return TreeIconId.CLASS;
|
||||
} else if (node instanceof ASTMethod) {
|
||||
return TreeIconId.METHOD;
|
||||
} else if (node instanceof ASTVariableDeclaration) {
|
||||
return TreeIconId.VARIABLE;
|
||||
}
|
||||
return super.getIcon(node);
|
||||
}
|
||||
|
||||
|
||||
private static final class MainAttrVisitor extends ApexParserVisitorAdapter {
|
||||
|
||||
private static final MainAttrVisitor INSTANCE = new MainAttrVisitor();
|
||||
|
||||
@Override
|
||||
public Object visit(ApexNode<?> node, Object data) {
|
||||
return null; // don't recurse
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTMethodCallExpression node, Object data) {
|
||||
return new Attribute(node, "MethodName", node.getMethodName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -12,6 +12,12 @@
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${basedir}/src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
|
@ -1,26 +1,13 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
|
||||
package net.sourceforge.pmd.lang.modelica.rule;
|
||||
|
||||
import net.sourceforge.pmd.lang.modelica.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ResolutionResult;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ResolvableEntity;
|
||||
/**
|
||||
* @deprecated Use {@link net.sourceforge.pmd.lang.modelica.rule.bestpractices.AmbiguousResolutionRule}
|
||||
*/
|
||||
public class AmbiguousResolutionRule extends net.sourceforge.pmd.lang.modelica.rule.bestpractices.AmbiguousResolutionRule {
|
||||
|
||||
public class AmbiguousResolutionRule extends AbstractModelicaRule {
|
||||
@Override
|
||||
public Object visit(ASTName node, Object data) {
|
||||
ResolutionResult<ResolvableEntity> candidates = node.getResolutionCandidates();
|
||||
if (candidates.isClashed()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Candidate resolutions: ");
|
||||
for (ResolvableEntity candidate: candidates.getBestCandidates()) {
|
||||
sb.append(candidate.getDescriptiveName());
|
||||
sb.append(", ");
|
||||
}
|
||||
addViolation(data, node, sb.substring(0, sb.length() - 2));
|
||||
}
|
||||
return super.visit(node, data);
|
||||
}
|
||||
}
|
||||
|
@ -1,50 +1,16 @@
|
||||
/**
|
||||
/*
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
|
||||
package net.sourceforge.pmd.lang.modelica.rule;
|
||||
|
||||
import net.sourceforge.pmd.lang.modelica.ast.ASTComponentReference;
|
||||
import net.sourceforge.pmd.lang.modelica.ast.ASTConnectClause;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ModelicaClassSpecialization;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ModelicaClassType;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ModelicaComponentDeclaration;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ResolutionResult;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ResolvableEntity;
|
||||
import net.sourceforge.pmd.lang.modelica.rule.bestpractices.ConnectUsingNonConnectorRule;
|
||||
|
||||
public class ConnectUsingNonConnector extends AbstractModelicaRule {
|
||||
private void reportIfViolated(ASTComponentReference ref, Object data) {
|
||||
ResolutionResult<ResolvableEntity> resolution = ref.getResolutionCandidates();
|
||||
if (!resolution.isUnresolved()) { // no false positive if not resolved at all
|
||||
ResolvableEntity firstDecl = resolution.getBestCandidates().get(0);
|
||||
if (firstDecl instanceof ModelicaComponentDeclaration) {
|
||||
ModelicaComponentDeclaration componentDecl = (ModelicaComponentDeclaration) firstDecl;
|
||||
ResolutionResult componentTypes = componentDecl.getTypeCandidates();
|
||||
if (!componentTypes.isUnresolved()) {
|
||||
if (componentTypes.getBestCandidates().get(0) instanceof ModelicaClassType) {
|
||||
ModelicaClassType classDecl = (ModelicaClassType) componentTypes.getBestCandidates().get(0);
|
||||
ModelicaClassSpecialization restriction = classDecl.getSpecialization();
|
||||
if (!classDecl.isConnectorLike()) {
|
||||
addViolation(data, ref, restriction.toString());
|
||||
}
|
||||
} else {
|
||||
addViolation(data, ref, firstDecl.getDescriptiveName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addViolation(data, ref, firstDecl.getDescriptiveName());
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @deprecated Use {@link ConnectUsingNonConnectorRule}
|
||||
*/
|
||||
@Deprecated
|
||||
public class ConnectUsingNonConnector extends ConnectUsingNonConnectorRule {
|
||||
|
||||
@Override
|
||||
public Object visit(ASTConnectClause node, Object data) {
|
||||
ASTComponentReference lhs = (ASTComponentReference) node.getChild(0);
|
||||
ASTComponentReference rhs = (ASTComponentReference) node.getChild(1);
|
||||
|
||||
reportIfViolated(lhs, data);
|
||||
reportIfViolated(rhs, data);
|
||||
|
||||
return super.visit(node, data);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.modelica.rule.bestpractices;
|
||||
|
||||
import net.sourceforge.pmd.lang.modelica.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ResolutionResult;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ResolvableEntity;
|
||||
import net.sourceforge.pmd.lang.modelica.rule.AbstractModelicaRule;
|
||||
|
||||
public class AmbiguousResolutionRule extends AbstractModelicaRule {
|
||||
@Override
|
||||
public Object visit(ASTName node, Object data) {
|
||||
ResolutionResult<ResolvableEntity> candidates = node.getResolutionCandidates();
|
||||
if (candidates.isClashed()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Candidate resolutions: ");
|
||||
for (ResolvableEntity candidate: candidates.getBestCandidates()) {
|
||||
sb.append(candidate.getDescriptiveName());
|
||||
sb.append(", ");
|
||||
}
|
||||
addViolation(data, node, sb.substring(0, sb.length() - 2));
|
||||
}
|
||||
return super.visit(node, data);
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.modelica.rule.bestpractices;
|
||||
|
||||
import net.sourceforge.pmd.lang.modelica.ast.ASTComponentReference;
|
||||
import net.sourceforge.pmd.lang.modelica.ast.ASTConnectClause;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ModelicaClassSpecialization;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ModelicaClassType;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ModelicaComponentDeclaration;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ResolutionResult;
|
||||
import net.sourceforge.pmd.lang.modelica.resolver.ResolvableEntity;
|
||||
import net.sourceforge.pmd.lang.modelica.rule.AbstractModelicaRule;
|
||||
|
||||
public class ConnectUsingNonConnectorRule extends AbstractModelicaRule {
|
||||
private void reportIfViolated(ASTComponentReference ref, Object data) {
|
||||
ResolutionResult<ResolvableEntity> resolution = ref.getResolutionCandidates();
|
||||
if (!resolution.isUnresolved()) { // no false positive if not resolved at all
|
||||
ResolvableEntity firstDecl = resolution.getBestCandidates().get(0);
|
||||
if (firstDecl instanceof ModelicaComponentDeclaration) {
|
||||
ModelicaComponentDeclaration componentDecl = (ModelicaComponentDeclaration) firstDecl;
|
||||
ResolutionResult componentTypes = componentDecl.getTypeCandidates();
|
||||
if (!componentTypes.isUnresolved()) {
|
||||
if (componentTypes.getBestCandidates().get(0) instanceof ModelicaClassType) {
|
||||
ModelicaClassType classDecl = (ModelicaClassType) componentTypes.getBestCandidates().get(0);
|
||||
ModelicaClassSpecialization restriction = classDecl.getSpecialization();
|
||||
if (!classDecl.isConnectorLike()) {
|
||||
addViolation(data, ref, restriction.toString());
|
||||
}
|
||||
} else {
|
||||
addViolation(data, ref, firstDecl.getDescriptiveName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addViolation(data, ref, firstDecl.getDescriptiveName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visit(ASTConnectClause node, Object data) {
|
||||
ASTComponentReference lhs = (ASTComponentReference) node.getChild(0);
|
||||
ASTComponentReference rhs = (ASTComponentReference) node.getChild(1);
|
||||
|
||||
reportIfViolated(lhs, data);
|
||||
reportIfViolated(rhs, data);
|
||||
|
||||
return super.visit(node, data);
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ Rules which enforce generally accepted best practices.
|
||||
|
||||
<rule name="ClassStartNameEqualsEndName"
|
||||
language="modelica"
|
||||
since="6.21.0"
|
||||
message="Class ends with an end clause with a different name"
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_modelica_bestpractices.html#classstartnameequalsendname"
|
||||
class="net.sourceforge.pmd.lang.rule.XPathRule">
|
||||
@ -40,9 +41,10 @@ end SomeOtherName /* should be SomeName */;
|
||||
|
||||
<rule name="ConnectUsingNonConnector"
|
||||
language="modelica"
|
||||
since="6.21.0"
|
||||
message="Arguments passed to `connect` should be connectors, not `{0}`"
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_modelica_bestpractices.html#connectusingnonconnector"
|
||||
class="net.sourceforge.pmd.lang.modelica.rule.ConnectUsingNonConnector">
|
||||
class="net.sourceforge.pmd.lang.modelica.rule.bestpractices.ConnectUsingNonConnectorRule">
|
||||
<description>
|
||||
Modelica specification requires passing connectors to the `connect` clause,
|
||||
while some implementations tolerate using it on plain variables, etc..
|
||||
@ -74,8 +76,9 @@ end Example;
|
||||
<rule name="AmbiguousResolution"
|
||||
language="modelica"
|
||||
message="Type resolution is ambiguous: {0}"
|
||||
since="6.21.0"
|
||||
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_modelica_bestpractices.html#ambiguousresolution"
|
||||
class="net.sourceforge.pmd.lang.modelica.rule.AmbiguousResolutionRule">
|
||||
class="net.sourceforge.pmd.lang.modelica.rule.bestpractices.AmbiguousResolutionRule">
|
||||
<description>
|
||||
There is multiple candidates for this type resolution. While generally this is not an error,
|
||||
this may indicate a bug.
|
||||
|
@ -284,10 +284,17 @@ public abstract class AbstractRuleSetFactoryTest {
|
||||
}
|
||||
|
||||
private List<String> getRuleSetFileNames(String language) throws IOException {
|
||||
List<String> ruleSetFileNames = new ArrayList<>();
|
||||
ruleSetFileNames.addAll(getRuleSetFileNames(language, "rulesets/" + language + "/rulesets.properties"));
|
||||
ruleSetFileNames.addAll(getRuleSetFileNames(language, "category/" + language + "/categories.properties"));
|
||||
return ruleSetFileNames;
|
||||
}
|
||||
|
||||
private List<String> getRuleSetFileNames(String language, String propertiesPath) throws IOException {
|
||||
List<String> ruleSetFileNames = new ArrayList<>();
|
||||
Properties properties = new Properties();
|
||||
@SuppressWarnings("PMD.CloseResource")
|
||||
InputStream input = getClass().getResourceAsStream("rulesets/" + language + "/rulesets.properties");
|
||||
InputStream input = getClass().getResourceAsStream(propertiesPath);
|
||||
if (input == null) {
|
||||
// this might happen if a language is only support by CPD, but not
|
||||
// by PMD
|
||||
@ -302,7 +309,6 @@ public abstract class AbstractRuleSetFactoryTest {
|
||||
while (st.hasMoreTokens()) {
|
||||
ruleSetFileNames.add(st.nextToken());
|
||||
}
|
||||
|
||||
return ruleSetFileNames;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user