-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[java] Groundwork for the upcoming metrics framework #409
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ow because of Typeres. Be sure to edit the tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, great work! I really like seeing the metrics framework evolving!
@@ -201,6 +201,16 @@ public boolean usesTypeResolution(Language language) { | |||
return false; | |||
} | |||
|
|||
public boolean usesMetrics(Language language) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add for this directly the javadocs. I know, "usesTyperesolution" above doesn't have the docs either, but somewhere we need to start :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right I'll document both then ;)
MeasuredTotal(12, "Measured total"), | ||
NonMeasuredTotal(13, "Non-measured total"), | ||
TotalPMD(14, "Total PMD"); | ||
MetricsVisitor(8, "Metrics visitor"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a minor thing: I think, I wouldn't name this here MetricsVisitor - maybe just Metrics? Since "Visitor" is just an implementation detail...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check
@@ -567,6 +567,10 @@ private void parseSingleRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSetB | |||
rule.setUsesTypeResolution(); | |||
} | |||
|
|||
if (hasAttributeSetTrue(ruleElement, "metrics")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll need to lookup myself, but I guess, we need to update somehow the XML schema / DTD. Otherwise every XML editor will complain, that the attribute "metrics" is not allowed and one cannot create a ruleset xml file, with rules, that use metrics ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! Is this repo the sources for http://pmd.sourceforge.net/
? In that case I think adding a line to this xsd definition, which is loaded by rulesets, would do the trick
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's one place, were the definition can be downloaded. But the master source is really in the main repo (under pmd-core): https://github.com/pmd/pmd/tree/master/pmd-core/src/main/resources
I'm not sure about whether we could just change the definition and keep the version/namespace the same (given that it is compatible) or whether we should change the namespace...
@@ -567,6 +567,10 @@ private void parseSingleRuleNode(RuleSetReferenceId ruleSetReferenceId, RuleSetB | |||
rule.setUsesTypeResolution(); | |||
} | |||
|
|||
if (hasAttributeSetTrue(ruleElement, "metrics")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And of course, we shouldn't forget about documenting this... but that's something for later.
if (isNested()) { | ||
ASTClassOrInterfaceDeclaration parent = this.getFirstParentOfType(ASTClassOrInterfaceDeclaration.class); | ||
QualifiedName parentQN = parent.getQualifiedName(); | ||
return QualifiedName.makeClassOf(parentQN, this.getImage()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we cache the qualifiedName in this.qualifiedName
here, too? For the other case (not isNested()
), we cache it. Since the AST doesn't change, I think, it's safe to cache it here the same way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's actually a nice recursive call 👍 Goes up the tree to the outer class. I hope, isNested()
returns false, then...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I forgot to cache it there! Well yes otherwise we'd get a nice NPE :)
*/ | ||
public enum OperationMetricKey { | ||
|
||
ATFD(new AtfdMetric()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering: is AFTD both a ClassMetric and a OperationMetric, or is this just an example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, ATFD is both
} | ||
} | ||
|
||
return foreignCalls / callQNames.size(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This look like an integer division. You'll need to cast one number to a double before dividing....
|
||
@Override | ||
public double computeFor(ASTClassOrInterfaceDeclaration node, PackageStats holder) { | ||
return node.getEndLine() - node.getBeginLine(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a very simple method to calculate the lines. It depends on the source code formatting. I don't know about the requirements for this particular metric, but maybe NCSS (non-commenting sourcecode statements) might be an alternative. It of course it a bit more complex to calculate...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't put much thought into it lol
I guess we could have both metrics, one version that counts with comments and the other not, and set which implementation will be used by rules that use LOC via a rule property.
public enum Role { | ||
GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC; | ||
|
||
public static final Role[] ALL = {GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The enum provides already a field values
which contains all the values of the enum in an array. So, no need to define ALL
manually :)
public enum Visibility { | ||
PUBLIC, PACKAGE, PROTECTED, PRIVATE, UNDEF; | ||
|
||
public static final Visibility[] ALL = {PUBLIC, PACKAGE, PROTECTED, PRIVATE}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here: you can use Visibility.values
instead
The creation methods now mostly take the node to describe as parameter. That way, the implementation of the class is less exposed, the creation methods can be overloaded and simplified in the AST nodes' classes. Only nested class do not do that. That is to keep the recursive call to getQualifiedName which would be much more complicated if it was called from QualifiedName rather than the AST node.
So we figured with @adangel that I should not wait too much to make a PR for my work on the metrics framework, given the increasing mess that is the history of this branch. In the future I'll do smaller PRs
Note: The framework is absolutely not functional, but should not break anything
Changelog
Changes to the AST
QualifiedName getQualifiedName()
, which retrieves the qualified name of the nodeQualifiedName
's implementation is nested insideQualifiableNode
New stuff
oom
(object oriented metrics) inlang.java
, to contain the frameworkoom.Metrics
: Façade of the frameworkoom.metrics
: will contain the implementations of the metrics (there are already some drafts in there)oom.visitor
: contains the visitor that will be executed before the rules and related classes. About the visitor:metrics
attribute set to truePackageStats
, which stores information about the methods and fields of each class. We useQualifiedName
to address the contents of the DS and make requestsSignature
classes. More info on signatures in my fork's wiki