Skip to content

Commit

Permalink
Merge branch '__rultor'
Browse files Browse the repository at this point in the history
  • Loading branch information
rultor committed Jan 25, 2019
2 parents 8e08c25 + 65f399d commit f5b7433
Show file tree
Hide file tree
Showing 11 changed files with 456 additions and 68 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ SOFTWARE.
<version>9.8.0-5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.llorllale</groupId>
<artifactId>cactoos-matchers</artifactId>
<version>0.13</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
14 changes: 12 additions & 2 deletions src/main/java/org/jpeek/skeleton/OpsOf.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
*/
package org.jpeek.skeleton;

import org.cactoos.Text;
import org.cactoos.text.TextOf;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.xembly.Directives;
Expand Down Expand Up @@ -63,16 +65,25 @@ public void visitFieldInsn(final int opcode, final String owner,
final String attr, final String dsc) {
super.visitFieldInsn(opcode, owner, attr, dsc);
this.target.addIf("ops").add("op");
final Text name;
if (opcode == Opcodes.GETFIELD) {
this.target.attr("code", "get");
name = new TextOf(attr);
} else if (opcode == Opcodes.PUTFIELD) {
this.target.attr("code", "put");
name = new TextOf(attr);
} else if (opcode == Opcodes.GETSTATIC) {
this.target.attr("code", "get_static");
name = new QualifiedName(owner, attr);
} else if (opcode == Opcodes.PUTSTATIC) {
this.target.attr("code", "put_static");
name = new QualifiedName(owner, attr);
} else {
name = new TextOf(attr);
}
this.target.set(attr).up().up();
this.target.set(
name
).up().up();
}

@Override
Expand All @@ -86,5 +97,4 @@ public void visitMethodInsn(final int opcode,
.set(owner.replace("/", ".").concat(".").concat(mtd))
.up().up();
}

}
55 changes: 55 additions & 0 deletions src/main/java/org/jpeek/skeleton/QualifiedName.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2017-2019 Yegor Bugayenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.jpeek.skeleton;

import org.cactoos.text.JoinedText;
import org.cactoos.text.TextEnvelope;
import org.cactoos.text.UncheckedText;

/**
* A fully qualified name of a field, an unambiguous name
* that specifies field without regard
* to the context of the call.
* @author Ilya Kharlamov (ilya.kharlamov@gmail.com)
* @version $Id$
* @since 0.29
*/
public final class QualifiedName extends TextEnvelope {
/**
* Ctor.
* @param owner The class the attribute belongs to
* @param attr The name of the field
*/
public QualifiedName(final String owner, final String attr) {
super(
new UncheckedText(
new JoinedText(
".",
owner.replace('/', '.'),
attr
)
)
);
}
}
22 changes: 15 additions & 7 deletions src/main/resources/org/jpeek/metrics/LCOM4.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,23 @@ SOFTWARE.
</xsl:template>
<xsl:template match="class">
<xsl:variable name="class_fqn" select="replace(string-join(../@id | @id, '.'), '^\.', '')"/>
<xsl:variable name="A" select="attributes/attribute[@static = 'false']/text()"/>
<xsl:variable name="attrs_fqn">
<xsl:for-each select="attributes/attribute">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:if test="@static='true' and $class_fqn != ''">
<xsl:value-of select="concat($class_fqn, '.')"/>
</xsl:if>
<xsl:value-of select="text()"/>
</xsl:copy>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="A" select="$attrs_fqn/*/text()"/>
<xsl:variable name="a" select="count($A)"/>
<xsl:variable name="M" select="methods/method"/>
<!-- Ctors are not methods -->
<xsl:variable name="M" select="methods/method[@ctor='false']"/>
<xsl:variable name="m" select="count($M)"/>
<!--
@todo #8:30min LCOM4: #156 needs to be fixed in order to avoid confusing access to
fields belonging to other classes as if they actually belong to this class.
Once #156 is fixed, refactor xpaths 'this_attrs' and 'other_attrs' accordingly.
-->
<!--
@todo #216:30min LCOM4: need to finish implementing the rest of the test cases. Only test case
"OneCommonAttribute", "NotCommonAttributes", "NotCommonAttributesWithAllArgsConstructor",
was implemented in this 30min ticket.
Expand Down Expand Up @@ -86,6 +93,7 @@ SOFTWARE.
</xsl:for-each>
</xsl:variable>
<xsl:copy>
<!-- LCOM4 is the number of connected components of G.-->
<xsl:attribute name="value">
<xsl:choose>
<xsl:when test="$m &lt; 2 or $a = 0">
Expand Down
18 changes: 15 additions & 3 deletions src/main/resources/org/jpeek/metrics/LCOM5.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,24 @@ SOFTWARE.
</metric>
</xsl:template>
<xsl:template match="class">
<xsl:variable name="class_fqn" select="replace(string-join(../@id | @id, '.'), '^\.', '')"/>
<xsl:variable name="attrs_fqn">
<xsl:for-each select="attributes/attribute">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:if test="@static='true' and $class_fqn != ''">
<xsl:value-of select="concat($class_fqn, '.')"/>
</xsl:if>
<xsl:value-of select="text()"/>
</xsl:copy>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="methods" select="methods/method"/>
<xsl:variable name="m" select="count($methods)"/>
<xsl:variable name="attributes" select="attributes/attribute/text()"/>
<xsl:variable name="a" select="count($attributes)"/>
<xsl:variable name="attributes" select="$attrs_fqn/*"/>
<xsl:variable name="a" select="count($attributes/text())"/>
<xsl:variable name="attributes_use">
<xsl:for-each select="$attributes">
<xsl:for-each select="$attributes/text()">
<xsl:variable name="attr" select="."/>
<count>
<xsl:value-of select="count($methods[ops/op = $attr])"/>
Expand Down
13 changes: 12 additions & 1 deletion src/main/resources/org/jpeek/metrics/OCC.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,18 @@ SOFTWARE.
</metric>
</xsl:template>
<xsl:template match="class">
<xsl:variable name="A" select="attributes/attribute/text()"/>
<xsl:variable name="class_fqn" select="replace(string-join(../@id | @id, '.'), '^\.', '')"/>
<xsl:variable name="attrs">
<xsl:for-each select="attributes/attribute">
<xsl:copy>
<xsl:if test="@static='true' and $class_fqn != ''">
<xsl:value-of select="concat($class_fqn, '.')"/>
</xsl:if>
<xsl:value-of select="text()"/>
</xsl:copy>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="A" select="$attrs/*/text()"/>
<xsl:variable name="M" select="methods/method"/>
<xsl:variable name="n" select="count($M)"/>
<xsl:variable name="connections">
Expand Down
3 changes: 0 additions & 3 deletions src/test/java/org/jpeek/MetricsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,6 @@ public static Collection<Object[]> targets() {
new Object[] {"OverloadMethods", "TLCOM", 0.0d},
new Object[] {"TwoCommonAttributes", "TLCOM", 4.0d},
new Object[] {"WithoutAttributes", "TLCOM", 1.0d},
new Object[] {"MethodMethodCalls", "LCOM4", 0.6d},
new Object[] {"OneCommonAttribute", "LCOM4", 1d},
new Object[] {"NotCommonAttributes", "LCOM4", 1.5d},
new Object[] {"Bar", "LCC", 0.0d},
new Object[] {"Foo", "LCC", 1.0d},
new Object[] {"MethodMethodCalls", "LCC", 0.1d},
Expand Down
168 changes: 168 additions & 0 deletions src/test/java/org/jpeek/metrics/Lcom4Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2017-2019 Yegor Bugayenko
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

package org.jpeek.metrics;

import org.cactoos.list.ListOf;
import org.junit.Ignore;
import org.junit.Test;

/**
* Test case for LCOM4
* LCOM4 = Logical Relatedness of Methods.
* Basically it's a graph disjoint set.
* I.e. it answers the the following question:
* "Into how many independent classes can you split this class?"
* @author Ilya Kharlamov (ilya.kharlamov@gmail.com)
* @version $Id$
* @since 0.28
* @checkstyle JavadocMethodCheck (500 lines)
* @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
* @checkstyle MagicNumberCheck (500 lines)
*/
public final class Lcom4Test {

/**
* Variable from the report.
*/
public static final String PAIRS = "pairs";

/**
* Variable from the report.
*/
public static final String ATTRIBUTES = "attributes";

/**
* Variable from the report.
*/
public static final String METHODS = "methods";

/**
* Path to XSL.
*/
private static final String XSL = "org/jpeek/metrics/LCOM4.xsl";

/**
* Tests the deep dependencies methodFour() -> methodTwo() -> methodOne().
* MethodMethodCalls.java
* - methodOne uses 'num' directly
* - methodTwo uses 'num' indirectly via methodOne
* - methodThree uses 'num' directly
* - methodFour uses 'num' indirectly via methodTwo and methodOne
* - methodFive does not use 'num' (this is an orphan method, ignored)
* Therefore the number of disjoint sets (LCOM4) should be 1
* since all the methods use the same num field.
* @todo #215:30min LCOM4: Graph algorithm to determine disjoint sets.
* Currently we can only identify the dependencies via only one graph hop
* so we can't trace methodFour that uses 'num' indirectly
* via methodTwo and methodOne.
* Calculating Disjoint sets (also known as Connected Components),
* requires a graph traversal algorithm like depth-first search.
* This one will be tricky to implement in XSLT.
* After implementing, remove the @Ignore.
*/
@Test
@Ignore
public void methodMethodCalls() throws Exception {
final MetricBase.Report report = new MetricBase(
Lcom4Test.XSL
).transform(
"MethodMethodCalls"
);
report.assertVariable(
Lcom4Test.METHODS,
new ListOf<>(
"methodOne()",
"methodTwo()",
"methodThree()",
"methodFour()",
"methodFive()"
).size()
);
report.assertVariable(Lcom4Test.ATTRIBUTES, 1);
report.assertValue(1.0f, 0.001f);
}

/**
* In OneCommonAttribute.java.
* - methodOne uses variable 'num'
* - methodTwo uses variable 'num'
* So this class only has a single disjoint set AKA (LCOM4)
* This is an ideal LCOM4 value = 1
*/
@Test
public void oneCommonAttribute() throws Exception {
final MetricBase.Report report = new MetricBase(
Lcom4Test.XSL
).transform(
"OneCommonAttribute"
);
report.assertVariable(
Lcom4Test.METHODS,
new ListOf<>(
"methodOne",
"methodTwo"
).size()
);
report.assertVariable(Lcom4Test.ATTRIBUTES, 1);
report.assertVariable(Lcom4Test.PAIRS, 1);
report.assertValue(1.0f, 0.001f);
}

/**
* In NotCommonAttributes.java
* - methodOne only uses 'num' variable
* - methodTwo only uses 'anotherNum' variable
* So basically there are two separate disjoint sets,
* or two separate classes under the same umbrella.
* So the value is 2.0
*/
@Test
public void notCommonAttributes() throws Exception {
final MetricBase.Report report = new MetricBase(
Lcom4Test.XSL
).transform(
"NotCommonAttributes"
);
report.assertVariable(Lcom4Test.ATTRIBUTES, 2);
report.assertVariable(Lcom4Test.PAIRS, 0);
report.assertValue(2.0f, 0.001f);
}

/**
* Should be the same as NotCommonAttributes.
* since constructors are not methods and should be ignored
*/
@Test
public void notCommonAttributesWithAllArgsConstructor() throws Exception {
final MetricBase.Report report = new MetricBase(
Lcom4Test.XSL
).transform(
"NotCommonAttributesWithAllArgsConstructor"
);
report.assertVariable(Lcom4Test.ATTRIBUTES, 2);
report.assertVariable(Lcom4Test.PAIRS, 0);
report.assertValue(2.0f, 0.001f);
}
}
Loading

2 comments on commit f5b7433

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on f5b7433 Jan 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 8-429ff082 disappeared from src/main/resources/org/jpeek/metrics/LCOM4.xsl, that's why I closed #215. Please, remember that the puzzle was not necessarily removed in this particular commit. Maybe it happened earlier, but we discovered this fact only now.

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on f5b7433 Jan 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 215-e68a3c3f discovered in src/test/java/org/jpeek/metrics/Lcom4Test.java and submitted as #310. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

Please sign in to comment.