Skip to content
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

№520 #560

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
466ac7f
Новый код устраняет возможные избыточные узлы путем проверки уникальн…
michaelwelly Jun 24, 2024
6fb119a
Изменен метод visitMethod() для извлечения и сохранения имени перемен…
michaelwelly Jun 24, 2024
ca92262
Исправлены 3 Warning:
michaelwelly Jun 24, 2024
514ce04
Исправлены 3 Warning:
michaelwelly Jun 24, 2024
78bb7bd
Merge pull request #2 from michaelwelly/520
michaelwelly Jun 24, 2024
e80b90b
Для задачи #524 "PROBLEM WITH CCM METRIC ADDITION V3", открытой 21 ма…
michaelwelly Jun 24, 2024
d821174
Merge pull request #3 from michaelwelly/524
michaelwelly Jun 24, 2024
922f3c6
Для задачи #524 "PROBLEM WITH CCM METRIC ADDITION V3", открытой 21 ма…
michaelwelly Jun 24, 2024
d95826a
Merge remote-tracking branch 'origin/524' into 524
michaelwelly Jun 24, 2024
eb83be1
Merge pull request #4 from michaelwelly/524
michaelwelly Jun 24, 2024
7371ed2
Выполнение вставленного кода, исключающего конструкторы с параметрами…
michaelwelly Jun 25, 2024
17c0b73
Merge pull request #5 from michaelwelly/554
michaelwelly Jun 25, 2024
b8969c1
"Исправлена ошибка компиляции, связанная с повторным определением пер…
michaelwelly Jun 26, 2024
bee463c
Merge remote-tracking branch 'origin/master'
michaelwelly Jun 26, 2024
a56b5e5
"Исправлена ошибка компиляции, связанная с повторным определением пер…
michaelwelly Jun 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ SOFTWARE.
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/jpeek/Metrics.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ public enum Metrics {
*/
CCM(false, null, null),


/**
* Class Connection Metric (CCM) metric.
* Measuring Class Cohesion in Object-Oriented Systems version 3
*/
CCM_V3(false, null, null),

/**
* Maximal Weighted Entropy metric. Modeling class cohesion as mixtures of latent topics
*/
Expand Down
64 changes: 25 additions & 39 deletions src/main/java/org/jpeek/graph/XmlGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
package org.jpeek.graph;

import com.jcabi.xml.XML;
import java.util.List;
import java.util.Map;

import java.util.*;

import org.cactoos.list.ListOf;
import org.cactoos.map.MapOf;
import org.cactoos.scalar.Sticky;
Expand Down Expand Up @@ -74,47 +75,32 @@ public List<Node> nodes() {
* @param cname Class in the skeleton this graph is for
* @return List of nodes
*/
private static List<Node> build(final Skeleton skeleton, final String pname,
final String cname) {
final Map<XML, Node> byxml = new MapOf<>(
method -> method,
method -> new Node.Simple(
new XmlMethodSignature(
skeleton.xml()
.nodes(
new FormattedText(
"//package[@id='%s']", pname
).toString()
).get(0)
.nodes(
new FormattedText(
"//class[@id='%s']", cname
).toString()
).get(0),
method
).asString()
),
skeleton.xml().nodes(
"//methods/method[@ctor='false' and @abstract='false']"
)
);
final Map<String, Node> byname = new MapOf<>(
Node::name,
node -> node,
byxml.values()
);
for (final Map.Entry<XML, Node> entry : byxml.entrySet()) {
final List<XML> calls = entry.getKey().nodes("ops/op[@code='call']");
final Node caller = entry.getValue();
for (final XML call : calls) {
final String name = new XmlMethodCall(call).toString();
if (byname.containsKey(name)) {
final Node callee = byname.get(name);
private static List<Node> build(final Skeleton skeleton, final String pname, final String cname) throws Exception {
final Map<XML, Node> byxml = new HashMap<>();
final Set<String> visitedNames = new HashSet<>();
for (XML methodXml : skeleton.xml().nodes("//methods/method[@ctor='false' and @abstract='false']")) {
String methodName = new XmlMethodSignature(skeleton.xml().nodes(new FormattedText("//package[@id='%s']", pname).toString())
.get(0)
.nodes(new FormattedText("//class[@id='%s']", cname).toString())
.get(0), methodXml).asString();
if (!visitedNames.contains(methodName)) {
Node.Simple node = new Node.Simple(methodName);
byxml.put(methodXml, node);
visitedNames.add(methodName);
}
}
for (Map.Entry<XML, Node> entry : byxml.entrySet()) {
XML methodXml = entry.getKey();
Node caller = entry.getValue();
for (XML call : methodXml.nodes("ops/op[@code='call']")) {
String calleeName = new XmlMethodCall(call).toString();
if (visitedNames.contains(calleeName)) {
Node callee = byxml.get(call); // assuming they exist in byxml
caller.connections().add(callee);
callee.connections().add(caller);
}
}
}
return new ListOf<>(byxml.values());
return new ArrayList<>(byxml.values());
}
}
125 changes: 60 additions & 65 deletions src/main/java/org/jpeek/skeleton/XmlClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;

import javassist.CannotCompileException;
import javassist.CtClass;
import org.cactoos.iterable.Joined;
import org.cactoos.iterable.Mapped;
import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
Expand All @@ -44,9 +46,9 @@
*
* <p>There is no thread-safety guarantee.</p>
*
* @checkstyle ParameterNumberCheck (500 lines)
* @see <a href="http://www.pitt.edu/~ckemerer/CK%20research%20papers/MetricForOOD_ChidamberKemerer94.pdf">A packages suite for object oriented design</a>
* @since 0.27
* @checkstyle ParameterNumberCheck (500 lines)
*/
final class XmlClass extends ClassVisitor implements Iterable<Directive> {

Expand All @@ -67,6 +69,7 @@ final class XmlClass extends ClassVisitor implements Iterable<Directive> {

/**
* Ctor.
*
* @param src The source
*/
XmlClass(final CtClass src) {
Expand All @@ -77,6 +80,7 @@ final class XmlClass extends ClassVisitor implements Iterable<Directive> {
}

@Override
@NotNull
public Iterator<Directive> iterator() {
final ClassReader reader;
try {
Expand All @@ -87,42 +91,42 @@ public Iterator<Directive> iterator() {
this.attrs.add("attributes");
reader.accept(this, 0);
return new Directives()
.append(this.attrs)
.up()
.add("methods")
.append(
new Joined<>(
new Mapped<>(
dirs -> new Directives().append(dirs).up(),
this.methods
)
.append(this.attrs)
.up()
.add("methods")
.append(
new Joined<>(
new Mapped<>(
dirs -> new Directives().append(dirs).up(),
this.methods
)
)
)
)
.up()
.iterator();
.up()
.iterator();
}

@Override
public FieldVisitor visitField(final int access,
final String name, final String desc,
final String signature, final Object value) {
final String name, final String desc,
final String signature, final Object value) {
this.attrs
.add("attribute")
.set(name)
.attr("type", desc.replaceAll(";$", ""))
.attr(
"public",
(access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC
)
.attr(
"final",
(access & Opcodes.ACC_FINAL) == Opcodes.ACC_FINAL
)
.attr(
"static",
(access & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC
)
.up();
.add("attribute")
.set(name)
.attr("type", desc.replaceAll(";$", ""))
.attr(
"public",
(access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC
)
.attr(
"final",
(access & Opcodes.ACC_FINAL) == Opcodes.ACC_FINAL
)
.attr(
"static",
(access & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC
)
.up();
return super.visitField(access, name, desc, signature, value);
}

Expand All @@ -140,53 +144,44 @@ public FieldVisitor visitField(final int access,
// - the `visitMethodInsn` arguments.
@Override
@SuppressWarnings(
{
"PMD.UseVarargs",
"PMD.UseObjectForClearerAPI"
}
{
"PMD.UseVarargs",
"PMD.UseObjectForClearerAPI"
}
)
public MethodVisitor visitMethod(final int access,
final String mtd, final String desc,
final String signature, final String[] exceptions) {
final String mtd, final String desc,
final String signature, final String[] exceptions) {
final Directives dirs = new Directives();
if ((access & Opcodes.ACC_SYNTHETIC) != Opcodes.ACC_SYNTHETIC) {
String visibility = "default";
if ((access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC) {
visibility = "public";
} else if (
(access & Opcodes.ACC_PROTECTED) == Opcodes.ACC_PROTECTED) {
} else if ((access & Opcodes.ACC_PROTECTED) == Opcodes.ACC_PROTECTED) {
visibility = "protected";
} else if ((access & Opcodes.ACC_PRIVATE) == Opcodes.ACC_PRIVATE) {
visibility = "private";
}

// Извлечение имени переменной из описания метода
String[] parts = desc.split("\\)");
String[] methodParts = parts[0].split("\\(");
String methodName = methodParts[0];
String[] variables = methodParts[1].split(",");
String variableName = variables[0]; // Предполагаем, что первая переменная - это та, к которой применен вызов метода

dirs.add("method")
.attr("name", mtd)
.attr("desc", desc)
.attr(
"ctor",
"<init>".equals(mtd) || "<clinit>".equals(mtd)
)
.attr(
"static",
(access & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC
)
.attr(
"abstract",
(access & Opcodes.ACC_ABSTRACT) == Opcodes.ACC_ABSTRACT
)
.attr(
"visibility",
visibility
)
.attr(
"bridge",
(access & Opcodes.ACC_BRIDGE) == Opcodes.ACC_BRIDGE
)
.append(new TypesOf(desc));
.attr("name", mtd)
.attr("variableName", variableName)
.attr("desc", desc)
.attr("ctor", "<init>".equals(mtd) || "<clinit>".equals(mtd))
.attr("static", (access & Opcodes.ACC_STATIC) == Opcodes.ACC_STATIC)
.attr("abstract", (access & Opcodes.ACC_ABSTRACT) == Opcodes.ACC_ABSTRACT)
.attr("visibility", visibility)
.attr("bridge", (access & Opcodes.ACC_BRIDGE) == Opcodes.ACC_BRIDGE)
.append(new TypesOf(desc));
this.methods.add(dirs);
}
return new OpsOf(
dirs, super.visitMethod(access, mtd, desc, signature, exceptions)
);
return new OpsOf(dirs, super.visitMethod(access, mtd, desc, signature, exceptions));
}
}
12 changes: 12 additions & 0 deletions src/main/resources/org/jpeek/metrics/LCOM4.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ SOFTWARE.
</xsl:variable>
<xsl:variable name="A" select="$attrs_fqn/*/text()"/>
<xsl:variable name="a" select="count($A)"/>
<!-- Считаем только методы (не конструкторы) -->
<xsl:variable name="M" select="methods/method[not(@ctor='true')]" />
<xsl:variable name="m" select="count($M)" />

<!-- Пересчитываем количество соединений методов без конструкторов -->
<xsl:variable name="E">
<xsl:for-each select="$M">
<xsl:variable name="this" select="."/>
<xsl:variable name="this_fullname" select="concat($class_fqn, '.', $this/@name)"/>
<!-- Остальной код остается неизменным -->
</xsl:for-each>
</xsl:variable>
<!-- Ctors are not methods -->
<xsl:variable name="M" select="methods/method[@ctor='false']"/>
<xsl:variable name="m" select="count($M)"/>
Expand Down
1 change: 1 addition & 0 deletions src/test/java/org/jpeek/XslReportTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ void createsFullXmlReport(@TempDir final Path output) throws Exception {
).affirm();
}


@Test
void setsCorrectSchemaLocation(@TempDir final Path output) throws Exception {
new XslReport(
Expand Down
Loading