From 8ac7a967e0c4f21cb920a61e5c50f98bdf1ed7cb Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Tue, 28 Mar 2017 16:30:06 +0300 Subject: [PATCH 01/18] Added fan-in metric for classes --- .../stockmetrics/JavaMetricProvider.java | 10 ++- .../FanInClassCalculator.java | 66 +++++++++++++++++++ .../classMetrics/FanInClassMetric.java | 52 +++++++++++++++ .../i18n/StockMetricsBundle.properties | 5 +- 4 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/classMetrics/FanInClassMetric.java diff --git a/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java b/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java index 6dfb4d5..3501786 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java @@ -104,6 +104,7 @@ private static void initializeClassMetrics(Collection metrics) { metrics.add(new TodoCommentCountClassMetric()); metrics.add(new TrueCommentRatioClassMetric()); metrics.add(new WeightedMethodComplexityMetric()); + metrics.add(new FanInClassMetric()); } private static void initializeInterfaceMetrics(Collection metrics) { @@ -329,7 +330,7 @@ private static void initializeProjectMetrics(Collection metrics) { @NotNull @Override public List getPrebuiltProfiles() { - final List out = new ArrayList(10); + final List out = new ArrayList(11); out.add(createChidamberKemererProfile()); out.add(createClassCountProfile()); out.add(createCodeSizeProfile()); @@ -340,9 +341,16 @@ public List getPrebuiltProfiles() { out.add(createMartinProfile()); out.add(createMoodProfile()); out.add(createTestProfile()); + out.add(createFanProfile()); return out; } + private static PrebuiltMetricProfile createFanProfile() { + final PrebuiltMetricProfile profile = new PrebuiltMetricProfile(StockMetricsBundle.message("fan.profile.name")); + profile.addMetric(FanInClassMetric.class); + return profile; + } + private static PrebuiltMetricProfile createChidamberKemererProfile() { final PrebuiltMetricProfile profile = new PrebuiltMetricProfile(StockMetricsBundle.message("chidamber.kemerer.metrics.profile.name")); diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java new file mode 100644 index 0000000..1f83626 --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java @@ -0,0 +1,66 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.classCalculators; + +import com.intellij.psi.JavaRecursiveElementVisitor; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiMethodCallExpression; + +import java.util.Stack; + +/** + * Created by Aleksandr Chudov on 27.03.2017. + */ +public class FanInClassCalculator extends ClassCalculator { + private final Stack fanInMetrics = new Stack(); + private int currentMetric = -1; + private final Stack classes = new Stack(); + + @Override + protected PsiElementVisitor createVisitor() { + return new Visitor(); + } + + private class Visitor extends JavaRecursiveElementVisitor { + + @Override + public void visitClass(PsiClass aClass) { + if (currentMetric != -1) { + fanInMetrics.push(Integer.valueOf(currentMetric)); + } + classes.push(aClass); + currentMetric = 0; + super.visitClass(aClass); + postMetric(aClass, currentMetric); + classes.pop(); + currentMetric = fanInMetrics.empty() ? -1 : fanInMetrics.pop().intValue(); + } + + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + super.visitMethodCallExpression(expression); + if (classes.empty()) { + return; + } + if (classes.peek().equals(expression.resolveMethod().getContainingClass())) { + return; + } + currentMetric++; + } + } +} diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classMetrics/FanInClassMetric.java b/stockmetrics/src/com/sixrr/stockmetrics/classMetrics/FanInClassMetric.java new file mode 100644 index 0000000..e600352 --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/classMetrics/FanInClassMetric.java @@ -0,0 +1,52 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.classMetrics; + +import com.sixrr.metrics.MetricCalculator; +import com.sixrr.metrics.MetricType; +import com.sixrr.stockmetrics.classCalculators.FanInClassCalculator; +import com.sixrr.stockmetrics.i18n.StockMetricsBundle; +import org.jetbrains.annotations.NotNull; + +/** + * Created by Aleksandr Chudov on 27.03.2017. + */ +public class FanInClassMetric extends ClassMetric { + @NotNull + @Override + public String getDisplayName() { + return StockMetricsBundle.message("fan.in.class.metric.display.name"); + } + + @NotNull + @Override + public String getAbbreviation() { + return StockMetricsBundle.message("fan.in.class.metric.abbreviation"); + } + + @NotNull + @Override + public MetricType getType() { + return MetricType.Count; + } + + @NotNull + @Override + public MetricCalculator createCalculator() { + return new FanInClassCalculator(); + } +} diff --git a/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties b/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties index 5d0a934..89205e4 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties +++ b/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties @@ -377,4 +377,7 @@ abstractness.display.name=Abstractness abstractness.abbreviation=A number.of.packages.abbreviation=P number.of.children.display.name=Number of children -number.of.children.abbreviation=NOC \ No newline at end of file +number.of.children.abbreviation=NOC +fan.profile.name=Fan metrics +fan.in.class.metric.display.name=Fan-In class metric +fan.in.class.metric.abbreviation=Fan-In \ No newline at end of file From 2393a18e376e78e9546f12d59d8754a7e5f32fc5 Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Tue, 28 Mar 2017 18:11:29 +0300 Subject: [PATCH 02/18] Added fan-out class metric --- .../stockmetrics/JavaMetricProvider.java | 2 + .../FanOutClassCalculator.java | 68 +++++++++++++++++++ .../classMetrics/FanOutClassMetric.java | 52 ++++++++++++++ .../i18n/StockMetricsBundle.properties | 4 +- 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/classMetrics/FanOutClassMetric.java diff --git a/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java b/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java index 3501786..b29bc3c 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java @@ -105,6 +105,7 @@ private static void initializeClassMetrics(Collection metrics) { metrics.add(new TrueCommentRatioClassMetric()); metrics.add(new WeightedMethodComplexityMetric()); metrics.add(new FanInClassMetric()); + metrics.add(new FanOutClassMetric()); } private static void initializeInterfaceMetrics(Collection metrics) { @@ -348,6 +349,7 @@ public List getPrebuiltProfiles() { private static PrebuiltMetricProfile createFanProfile() { final PrebuiltMetricProfile profile = new PrebuiltMetricProfile(StockMetricsBundle.message("fan.profile.name")); profile.addMetric(FanInClassMetric.class); + profile.addMetric(FanOutClassMetric.class); return profile; } diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java new file mode 100644 index 0000000..a43b35c --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java @@ -0,0 +1,68 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.classCalculators; + +import com.intellij.psi.JavaRecursiveElementVisitor; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiMethodCallExpression; + +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + +/** + * Created by Aleksandr Chudov on 28.03.2017. + */ +public class FanOutClassCalculator extends ClassCalculator { + private final Map metrics = new HashMap(); + private final Stack classes = new Stack(); + + @Override + public void endMetricsRun() { + for (Map.Entry e : metrics.entrySet()) { + postMetric(e.getKey(), e.getValue()); + } + super.endMetricsRun(); + } + + @Override + protected PsiElementVisitor createVisitor() { + return new Visitor(); + } + + private class Visitor extends JavaRecursiveElementVisitor { + @Override + public void visitClass(PsiClass aClass) { + classes.push(aClass); + if (!metrics.containsKey(aClass)) + metrics.put(aClass, 0); + super.visitClass(aClass); + classes.pop(); + } + + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + final PsiClass aClass = expression.resolveMethod().getContainingClass(); + if (classes.empty() || classes.peek().equals(aClass)) { + return; + } + int metric = metrics.containsKey(aClass) ? metrics.get(aClass).intValue() : 0; + metrics.put(aClass, metric + 1); + } + } +} diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classMetrics/FanOutClassMetric.java b/stockmetrics/src/com/sixrr/stockmetrics/classMetrics/FanOutClassMetric.java new file mode 100644 index 0000000..8ca0d33 --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/classMetrics/FanOutClassMetric.java @@ -0,0 +1,52 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.classMetrics; + +import com.sixrr.metrics.MetricCalculator; +import com.sixrr.metrics.MetricType; +import com.sixrr.stockmetrics.classCalculators.FanOutClassCalculator; +import com.sixrr.stockmetrics.i18n.StockMetricsBundle; +import org.jetbrains.annotations.NotNull; + +/** + * Created by Aleksandr Chudov on 28.03.2017. + */ +public class FanOutClassMetric extends ClassMetric { + @NotNull + @Override + public String getDisplayName() { + return StockMetricsBundle.message("fan.out.class.metric.display.name"); + } + + @NotNull + @Override + public String getAbbreviation() { + return StockMetricsBundle.message("fan.out.class.metric.abbreviation"); + } + + @NotNull + @Override + public MetricType getType() { + return MetricType.Count; + } + + @NotNull + @Override + public MetricCalculator createCalculator() { + return new FanOutClassCalculator(); + } +} diff --git a/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties b/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties index 89205e4..24c209a 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties +++ b/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties @@ -380,4 +380,6 @@ number.of.children.display.name=Number of children number.of.children.abbreviation=NOC fan.profile.name=Fan metrics fan.in.class.metric.display.name=Fan-In class metric -fan.in.class.metric.abbreviation=Fan-In \ No newline at end of file +fan.in.class.metric.abbreviation=Fan-In +fan.out.class.metric.display.name=Fan-Out class metric +fan.out.class.metric.abbreviation=Fan-Out \ No newline at end of file From 65bad440efc07be7ed007035d8e02ccdb0298a1e Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Sun, 2 Apr 2017 16:42:15 +0300 Subject: [PATCH 03/18] Fixed NPE when calls method from unexisting class --- .../classCalculators/FanInClassCalculator.java | 8 +++----- .../classCalculators/FanOutClassCalculator.java | 12 +++++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java index 1f83626..9791b84 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java @@ -16,10 +16,7 @@ package com.sixrr.stockmetrics.classCalculators; -import com.intellij.psi.JavaRecursiveElementVisitor; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiMethodCallExpression; +import com.intellij.psi.*; import java.util.Stack; @@ -57,7 +54,8 @@ public void visitMethodCallExpression(PsiMethodCallExpression expression) { if (classes.empty()) { return; } - if (classes.peek().equals(expression.resolveMethod().getContainingClass())) { + final PsiMethod method = expression.resolveMethod(); + if (method == null || classes.peek().equals(method.getContainingClass())) { return; } currentMetric++; diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java index a43b35c..9a6375f 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java @@ -16,10 +16,7 @@ package com.sixrr.stockmetrics.classCalculators; -import com.intellij.psi.JavaRecursiveElementVisitor; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiMethodCallExpression; +import com.intellij.psi.*; import java.util.HashMap; import java.util.Map; @@ -57,7 +54,12 @@ public void visitClass(PsiClass aClass) { @Override public void visitMethodCallExpression(PsiMethodCallExpression expression) { - final PsiClass aClass = expression.resolveMethod().getContainingClass(); + super.visitMethodCallExpression(expression); + final PsiMethod method = expression.resolveMethod(); + if (method == null) { + return; + } + final PsiClass aClass = method.getContainingClass(); if (classes.empty() || classes.peek().equals(aClass)) { return; } From fcfe7236008e058d8c66c31b2cbc76831bde4572 Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Sun, 2 Apr 2017 16:58:45 +0300 Subject: [PATCH 04/18] Post Fan-Out metric only for classes from scope --- .../classCalculators/FanOutClassCalculator.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java index 9a6375f..bad6b7e 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java @@ -18,21 +18,20 @@ import com.intellij.psi.*; -import java.util.HashMap; -import java.util.Map; -import java.util.Stack; +import java.util.*; /** * Created by Aleksandr Chudov on 28.03.2017. */ public class FanOutClassCalculator extends ClassCalculator { private final Map metrics = new HashMap(); + private final Collection visitClasses = new ArrayList(); private final Stack classes = new Stack(); @Override public void endMetricsRun() { - for (Map.Entry e : metrics.entrySet()) { - postMetric(e.getKey(), e.getValue()); + for (PsiClass aClass : visitClasses) { + postMetric(aClass, metrics.get(aClass)); } super.endMetricsRun(); } @@ -46,8 +45,10 @@ private class Visitor extends JavaRecursiveElementVisitor { @Override public void visitClass(PsiClass aClass) { classes.push(aClass); - if (!metrics.containsKey(aClass)) + visitClasses.add(aClass); + if (!metrics.containsKey(aClass)) { metrics.put(aClass, 0); + } super.visitClass(aClass); classes.pop(); } From 59fb53f3d3cb1d52a8d902e5cec2555cf11caea7 Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Sun, 2 Apr 2017 17:51:10 +0300 Subject: [PATCH 05/18] Added Fan-In method metric --- .../stockmetrics/JavaMetricProvider.java | 2 + .../i18n/StockMetricsBundle.properties | 4 +- .../FanInMethodCalculator.java | 63 +++++++++++++++++++ .../methodMetrics/FanInMethodMetric.java | 53 ++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/methodMetrics/FanInMethodMetric.java diff --git a/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java b/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java index b29bc3c..e291e22 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java @@ -183,6 +183,7 @@ private static void initializeMethodMetrics(Collection metrics) { metrics.add(new SourceLinesOfCodeMethodMetric()); metrics.add(new TodoCommentCountMethodMetric()); metrics.add(new TrueCommentRatioMethodMetric()); + metrics.add(new FanInMethodMetric()); } private static void initializeModuleMetrics(Collection metrics) { @@ -350,6 +351,7 @@ private static PrebuiltMetricProfile createFanProfile() { final PrebuiltMetricProfile profile = new PrebuiltMetricProfile(StockMetricsBundle.message("fan.profile.name")); profile.addMetric(FanInClassMetric.class); profile.addMetric(FanOutClassMetric.class); + profile.addMetric(FanInMethodMetric.class); return profile; } diff --git a/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties b/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties index 24c209a..6e096d7 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties +++ b/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties @@ -382,4 +382,6 @@ fan.profile.name=Fan metrics fan.in.class.metric.display.name=Fan-In class metric fan.in.class.metric.abbreviation=Fan-In fan.out.class.metric.display.name=Fan-Out class metric -fan.out.class.metric.abbreviation=Fan-Out \ No newline at end of file +fan.out.class.metric.abbreviation=Fan-Out +fan.in.method.metric.display.name=Fan-In method metric +fan.in.method.metric.abbreviation=FIM \ No newline at end of file diff --git a/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java new file mode 100644 index 0000000..20490af --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java @@ -0,0 +1,63 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.methodCalculators; + +import com.intellij.psi.*; + +import java.util.Stack; + +/** + * Created by Aleksandr Chudov on 02.04.2017. + */ +public class FanInMethodCalculator extends MethodCalculator { + private final Stack fanInMetrics = new Stack(); + private int currentMetric = -1; + private final Stack methods = new Stack(); + + @Override + protected PsiElementVisitor createVisitor() { + return new Visitor(); + } + + private class Visitor extends JavaRecursiveElementVisitor { + @Override + public void visitMethod(PsiMethod method) { + if (currentMetric != -1) { + fanInMetrics.push(Integer.valueOf(currentMetric)); + } + methods.push(method); + currentMetric = 0; + super.visitMethod(method); + postMetric(method, currentMetric); + methods.pop(); + currentMetric = fanInMetrics.empty() ? -1 : fanInMetrics.pop().intValue(); + } + + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + super.visitMethodCallExpression(expression); + if (methods.empty()) { + return; + } + final PsiMethod method = expression.resolveMethod(); + if (method == null || methods.peek().equals(method)) { + return; + } + currentMetric++; + } + } +} diff --git a/stockmetrics/src/com/sixrr/stockmetrics/methodMetrics/FanInMethodMetric.java b/stockmetrics/src/com/sixrr/stockmetrics/methodMetrics/FanInMethodMetric.java new file mode 100644 index 0000000..31dea1d --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/methodMetrics/FanInMethodMetric.java @@ -0,0 +1,53 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.methodMetrics; + +import com.sixrr.metrics.MetricCalculator; +import com.sixrr.metrics.MetricType; +import com.sixrr.stockmetrics.i18n.StockMetricsBundle; +import com.sixrr.stockmetrics.methodCalculators.FanInMethodCalculator; +import com.sixrr.stockmetrics.methodCalculators.MethodCalculator; +import org.jetbrains.annotations.NotNull; + +/** + * Created by Aleksandr Chudov on 02.04.2017. + */ +public class FanInMethodMetric extends MethodMetric { + @NotNull + @Override + public String getDisplayName() { + return StockMetricsBundle.message("fan.in.method.metric.display.name"); + } + + @NotNull + @Override + public String getAbbreviation() { + return StockMetricsBundle.message("fan.in.method.metric.abbreviation"); + } + + @NotNull + @Override + public MetricType getType() { + return MetricType.Count; + } + + @NotNull + @Override + public MetricCalculator createCalculator() { + return new FanInMethodCalculator(); + } +} From 20790844e326473c1e696d0d334d5d315ad489b6 Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Sun, 2 Apr 2017 18:10:53 +0300 Subject: [PATCH 06/18] Adde Fan-Out method metric --- .../stockmetrics/JavaMetricProvider.java | 2 + .../i18n/StockMetricsBundle.properties | 4 +- .../FanOutMethodCalculator.java | 67 +++++++++++++++++++ .../methodMetrics/FanOutMethodMetric.java | 52 ++++++++++++++ 4 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/methodMetrics/FanOutMethodMetric.java diff --git a/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java b/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java index e291e22..4fea181 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/JavaMetricProvider.java @@ -184,6 +184,7 @@ private static void initializeMethodMetrics(Collection metrics) { metrics.add(new TodoCommentCountMethodMetric()); metrics.add(new TrueCommentRatioMethodMetric()); metrics.add(new FanInMethodMetric()); + metrics.add(new FanOutMethodMetric()); } private static void initializeModuleMetrics(Collection metrics) { @@ -352,6 +353,7 @@ private static PrebuiltMetricProfile createFanProfile() { profile.addMetric(FanInClassMetric.class); profile.addMetric(FanOutClassMetric.class); profile.addMetric(FanInMethodMetric.class); + profile.addMetric(FanOutMethodMetric.class); return profile; } diff --git a/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties b/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties index 6e096d7..7b4bd48 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties +++ b/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties @@ -384,4 +384,6 @@ fan.in.class.metric.abbreviation=Fan-In fan.out.class.metric.display.name=Fan-Out class metric fan.out.class.metric.abbreviation=Fan-Out fan.in.method.metric.display.name=Fan-In method metric -fan.in.method.metric.abbreviation=FIM \ No newline at end of file +fan.in.method.metric.abbreviation=FIM +fan.out.method.metric.display.name=Fan-Out method metric +fan.out.method.metric.abbreviation=FOM \ No newline at end of file diff --git a/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java new file mode 100644 index 0000000..eff8c1f --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java @@ -0,0 +1,67 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.methodCalculators; + +import com.intellij.psi.*; + +import java.util.*; + +/** + * Created by Aleksandr Chudov on 02.04.2017. + */ +public class FanOutMethodCalculator extends MethodCalculator { + private final Map metrics = new HashMap(); + private final Collection visitMethods = new ArrayList(); + private final Stack methods = new Stack(); + + @Override + public void endMetricsRun() { + for (PsiMethod method : visitMethods) { + postMetric(method, metrics.get(method)); + } + super.endMetricsRun(); + } + + @Override + protected PsiElementVisitor createVisitor() { + return new Visitor(); + } + + private class Visitor extends JavaRecursiveElementVisitor { + @Override + public void visitMethod(PsiMethod method) { + methods.push(method); + visitMethods.add(method); + if (!metrics.containsKey(method)) { + metrics.put(method, 0); + } + super.visitMethod(method); + methods.pop(); + } + + @Override + public void visitMethodCallExpression(PsiMethodCallExpression expression) { + super.visitMethodCallExpression(expression); + final PsiMethod method = expression.resolveMethod(); + if (method == null || methods.empty() || methods.peek().equals(method)) { + return; + } + int metric = metrics.containsKey(method) ? metrics.get(method).intValue() : 0; + metrics.put(method, metric + 1); + } + } +} diff --git a/stockmetrics/src/com/sixrr/stockmetrics/methodMetrics/FanOutMethodMetric.java b/stockmetrics/src/com/sixrr/stockmetrics/methodMetrics/FanOutMethodMetric.java new file mode 100644 index 0000000..acee8b9 --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/methodMetrics/FanOutMethodMetric.java @@ -0,0 +1,52 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.methodMetrics; + +import com.sixrr.metrics.MetricCalculator; +import com.sixrr.metrics.MetricType; +import com.sixrr.stockmetrics.i18n.StockMetricsBundle; +import com.sixrr.stockmetrics.methodCalculators.FanOutMethodCalculator; +import org.jetbrains.annotations.NotNull; + +/** + * Created by Aleksandr Chudov on 02.04.2017. + */ +public class FanOutMethodMetric extends MethodMetric { + @NotNull + @Override + public String getDisplayName() { + return StockMetricsBundle.message("fan.out.method.metric.display.name"); + } + + @NotNull + @Override + public String getAbbreviation() { + return StockMetricsBundle.message("fan.out.method.metric.abbreviation"); + } + + @NotNull + @Override + public MetricType getType() { + return MetricType.Count; + } + + @NotNull + @Override + public MetricCalculator createCalculator() { + return new FanOutMethodCalculator(); + } +} From bc5c68a5918b067fb87d73a45be111c97a323eb5 Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Sun, 2 Apr 2017 18:11:45 +0300 Subject: [PATCH 07/18] Fix abbreviations for fan class metrics --- .../com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties b/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties index 7b4bd48..297d14e 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties +++ b/stockmetrics/src/com/sixrr/stockmetrics/i18n/StockMetricsBundle.properties @@ -380,9 +380,9 @@ number.of.children.display.name=Number of children number.of.children.abbreviation=NOC fan.profile.name=Fan metrics fan.in.class.metric.display.name=Fan-In class metric -fan.in.class.metric.abbreviation=Fan-In +fan.in.class.metric.abbreviation=FIC fan.out.class.metric.display.name=Fan-Out class metric -fan.out.class.metric.abbreviation=Fan-Out +fan.out.class.metric.abbreviation=FOC fan.in.method.metric.display.name=Fan-In method metric fan.in.method.metric.abbreviation=FIM fan.out.method.metric.display.name=Fan-Out method metric From a97bac6481ce8717af91f933bf1f818bd0aed050 Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Tue, 11 Apr 2017 17:52:24 +0300 Subject: [PATCH 08/18] Fix fan method metrics --- .../FanOutClassCalculator.java | 21 ++++----- .../FanInMethodCalculator.java | 37 +++++++++------- .../FanOutMethodCalculator.java | 44 ++++++++++--------- 3 files changed, 52 insertions(+), 50 deletions(-) diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java index bad6b7e..88109de 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java @@ -17,21 +17,22 @@ package com.sixrr.stockmetrics.classCalculators; import com.intellij.psi.*; +import com.sixrr.metrics.utils.BucketedCount; import java.util.*; /** - * Created by Aleksandr Chudov on 28.03.2017. + * @author Aleksandr Chudov. */ public class FanOutClassCalculator extends ClassCalculator { - private final Map metrics = new HashMap(); - private final Collection visitClasses = new ArrayList(); + private final BucketedCount metrics = new BucketedCount(); + private final Collection visitedClasses = new ArrayList(); private final Stack classes = new Stack(); @Override public void endMetricsRun() { - for (PsiClass aClass : visitClasses) { - postMetric(aClass, metrics.get(aClass)); + for (PsiClass aClass : visitedClasses) { + postMetric(aClass, metrics.getBucketValue(aClass)); } super.endMetricsRun(); } @@ -45,10 +46,7 @@ private class Visitor extends JavaRecursiveElementVisitor { @Override public void visitClass(PsiClass aClass) { classes.push(aClass); - visitClasses.add(aClass); - if (!metrics.containsKey(aClass)) { - metrics.put(aClass, 0); - } + visitedClasses.add(aClass); super.visitClass(aClass); classes.pop(); } @@ -61,11 +59,10 @@ public void visitMethodCallExpression(PsiMethodCallExpression expression) { return; } final PsiClass aClass = method.getContainingClass(); - if (classes.empty() || classes.peek().equals(aClass)) { + if (aClass == null || classes.empty() || classes.peek().equals(aClass)) { return; } - int metric = metrics.containsKey(aClass) ? metrics.get(aClass).intValue() : 0; - metrics.put(aClass, metric + 1); + metrics.incrementBucketValue(aClass); } } } diff --git a/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java index 20490af..32aea4a 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java @@ -17,17 +17,28 @@ package com.sixrr.stockmetrics.methodCalculators; import com.intellij.psi.*; +import com.sixrr.metrics.utils.BucketedCount; +import java.util.ArrayList; +import java.util.Collection; import java.util.Stack; /** - * Created by Aleksandr Chudov on 02.04.2017. + * @author Aleksandr Chudov. */ public class FanInMethodCalculator extends MethodCalculator { - private final Stack fanInMetrics = new Stack(); - private int currentMetric = -1; + private final BucketedCount metrics = new BucketedCount(); + private final Collection visitedMethods = new ArrayList(); private final Stack methods = new Stack(); + @Override + public void endMetricsRun() { + for (PsiMethod method : visitedMethods) { + postMetric(method, metrics.getBucketValue(method)); + } + super.endMetricsRun(); + } + @Override protected PsiElementVisitor createVisitor() { return new Visitor(); @@ -36,28 +47,20 @@ protected PsiElementVisitor createVisitor() { private class Visitor extends JavaRecursiveElementVisitor { @Override public void visitMethod(PsiMethod method) { - if (currentMetric != -1) { - fanInMetrics.push(Integer.valueOf(currentMetric)); - } methods.push(method); - currentMetric = 0; + visitedMethods.add(method); super.visitMethod(method); - postMetric(method, currentMetric); methods.pop(); - currentMetric = fanInMetrics.empty() ? -1 : fanInMetrics.pop().intValue(); } @Override - public void visitMethodCallExpression(PsiMethodCallExpression expression) { - super.visitMethodCallExpression(expression); - if (methods.empty()) { - return; - } - final PsiMethod method = expression.resolveMethod(); - if (method == null || methods.peek().equals(method)) { + public void visitCallExpression(PsiCallExpression callExpression) { + super.visitCallExpression(callExpression); + final PsiMethod method = callExpression.resolveMethod(); + if (method == null || !methods.empty() && methods.peek().equals(method)) { return; } - currentMetric++; + metrics.incrementBucketValue(method); } } } diff --git a/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java index eff8c1f..2706bab 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java @@ -17,51 +17,53 @@ package com.sixrr.stockmetrics.methodCalculators; import com.intellij.psi.*; +import com.sixrr.metrics.utils.BucketedCount; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Stack; /** - * Created by Aleksandr Chudov on 02.04.2017. + * @author Aleksandr Chudov. */ public class FanOutMethodCalculator extends MethodCalculator { - private final Map metrics = new HashMap(); - private final Collection visitMethods = new ArrayList(); + private final Collection visitedMethods = new ArrayList(); + private final BucketedCount metrics = new BucketedCount(); private final Stack methods = new Stack(); @Override - public void endMetricsRun() { - for (PsiMethod method : visitMethods) { - postMetric(method, metrics.get(method)); - } - super.endMetricsRun(); + protected PsiElementVisitor createVisitor() { + return new Visitor(); } @Override - protected PsiElementVisitor createVisitor() { - return new Visitor(); + public void endMetricsRun() { + for (final PsiMethod method : visitedMethods) { + postMetric(method, metrics.getBucketValue(method)); + } + super.endMetricsRun(); } private class Visitor extends JavaRecursiveElementVisitor { @Override public void visitMethod(PsiMethod method) { methods.push(method); - visitMethods.add(method); - if (!metrics.containsKey(method)) { - metrics.put(method, 0); - } + visitedMethods.add(method); super.visitMethod(method); methods.pop(); } @Override - public void visitMethodCallExpression(PsiMethodCallExpression expression) { - super.visitMethodCallExpression(expression); - final PsiMethod method = expression.resolveMethod(); - if (method == null || methods.empty() || methods.peek().equals(method)) { + public void visitCallExpression(PsiCallExpression callExpression) { + super.visitCallExpression(callExpression); + if (methods.empty()) { + return; + } + final PsiMethod method = callExpression.resolveMethod(); + if (method == null || methods.peek().equals(method)) { return; } - int metric = metrics.containsKey(method) ? metrics.get(method).intValue() : 0; - metrics.put(method, metric + 1); + metrics.incrementBucketValue(methods.peek()); } } } From 97ad1e5ce45ca3a66c4c5f10c77156f6fc260629 Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Fri, 14 Apr 2017 23:33:29 +0300 Subject: [PATCH 09/18] Fix fan class metrics --- .../FanInClassCalculator.java | 44 ++++++++++++------- .../FanOutClassCalculator.java | 42 +++++++++++------- 2 files changed, 55 insertions(+), 31 deletions(-) diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java index 9791b84..28564c4 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java @@ -18,14 +18,20 @@ import com.intellij.psi.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.Stack; /** - * Created by Aleksandr Chudov on 27.03.2017. + * @author Aleksandr Chudov. */ public class FanInClassCalculator extends ClassCalculator { - private final Stack fanInMetrics = new Stack(); - private int currentMetric = -1; + private final Map> metrics = new HashMap>(); + private final Collection visitedClasses = new ArrayList(); private final Stack classes = new Stack(); @Override @@ -33,32 +39,40 @@ protected PsiElementVisitor createVisitor() { return new Visitor(); } - private class Visitor extends JavaRecursiveElementVisitor { + @Override + public void endMetricsRun() { + for (PsiClass aClass : visitedClasses) { + postMetric(aClass, metrics.get(aClass).size()); + } + super.endMetricsRun(); + } + private class Visitor extends JavaRecursiveElementVisitor { @Override public void visitClass(PsiClass aClass) { - if (currentMetric != -1) { - fanInMetrics.push(Integer.valueOf(currentMetric)); + if (!metrics.containsKey(aClass)) { + metrics.put(aClass, new HashSet()); } classes.push(aClass); - currentMetric = 0; + visitedClasses.add(aClass); super.visitClass(aClass); - postMetric(aClass, currentMetric); classes.pop(); - currentMetric = fanInMetrics.empty() ? -1 : fanInMetrics.pop().intValue(); } @Override - public void visitMethodCallExpression(PsiMethodCallExpression expression) { - super.visitMethodCallExpression(expression); - if (classes.empty()) { + public void visitCallExpression(PsiCallExpression callExpression) { + super.visitCallExpression(callExpression); + final PsiMethod method = callExpression.resolveMethod(); + if (method == null) { return; } - final PsiMethod method = expression.resolveMethod(); - if (method == null || classes.peek().equals(method.getContainingClass())) { + final PsiClass aClass = method.getContainingClass(); + if (aClass == null || classes.empty() || classes.peek().equals(aClass)) { return; } - currentMetric++; + final Set s = metrics.containsKey(aClass) ? metrics.get(aClass) : new HashSet(); + s.add(classes.peek()); + metrics.put(aClass, s); } } } diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java index 88109de..892bb8f 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java @@ -17,34 +17,41 @@ package com.sixrr.stockmetrics.classCalculators; import com.intellij.psi.*; -import com.sixrr.metrics.utils.BucketedCount; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.Stack; /** * @author Aleksandr Chudov. */ public class FanOutClassCalculator extends ClassCalculator { - private final BucketedCount metrics = new BucketedCount(); + private final Map> metrics = new HashMap>(); private final Collection visitedClasses = new ArrayList(); private final Stack classes = new Stack(); @Override - public void endMetricsRun() { - for (PsiClass aClass : visitedClasses) { - postMetric(aClass, metrics.getBucketValue(aClass)); - } - super.endMetricsRun(); + protected PsiElementVisitor createVisitor() { + return new Visitor(); } @Override - protected PsiElementVisitor createVisitor() { - return new Visitor(); + public void endMetricsRun() { + for (final PsiClass aClass : visitedClasses) { + postMetric(aClass, metrics.get(aClass).size()); + } + super.endMetricsRun(); } private class Visitor extends JavaRecursiveElementVisitor { + @Override public void visitClass(PsiClass aClass) { + metrics.put(aClass, new HashSet()); classes.push(aClass); visitedClasses.add(aClass); super.visitClass(aClass); @@ -52,17 +59,20 @@ public void visitClass(PsiClass aClass) { } @Override - public void visitMethodCallExpression(PsiMethodCallExpression expression) { - super.visitMethodCallExpression(expression); - final PsiMethod method = expression.resolveMethod(); - if (method == null) { + public void visitCallExpression(PsiCallExpression callExpression) { + super.visitCallExpression(callExpression); + if (classes.empty()) { + return; + } + final PsiMethod method = callExpression.resolveMethod(); + if (method == null || classes.peek().equals(method.getContainingClass())) { return; } final PsiClass aClass = method.getContainingClass(); - if (aClass == null || classes.empty() || classes.peek().equals(aClass)) { + if (aClass == null) { return; } - metrics.incrementBucketValue(aClass); + metrics.get(classes.peek()).add(aClass); } } } From 3caec27ba26e38d8a50788043c458b9f10cc4f01 Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Tue, 2 May 2017 15:19:12 +0300 Subject: [PATCH 10/18] Add field usage calculation --- .../stockmetrics/utils/FieldUsageMap.java | 37 +++++++ .../stockmetrics/utils/FieldUsageMapImpl.java | 100 ++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/utils/FieldUsageMap.java create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/utils/FieldUsageMapImpl.java diff --git a/stockmetrics/src/com/sixrr/stockmetrics/utils/FieldUsageMap.java b/stockmetrics/src/com/sixrr/stockmetrics/utils/FieldUsageMap.java new file mode 100644 index 0000000..e6b7e59 --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/utils/FieldUsageMap.java @@ -0,0 +1,37 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.utils; + +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiReference; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +/** + * @author Aleksandr Chudov. + */ +public interface FieldUsageMap { + @NotNull + Set calculateFieldUsagePoints(PsiField field); + + @NotNull + Set calculateTestFieldUsagePoints(PsiField field); + + @NotNull + Set calculateProductFieldUsagePoints(PsiField field); +} diff --git a/stockmetrics/src/com/sixrr/stockmetrics/utils/FieldUsageMapImpl.java b/stockmetrics/src/com/sixrr/stockmetrics/utils/FieldUsageMapImpl.java new file mode 100644 index 0000000..456275e --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/utils/FieldUsageMapImpl.java @@ -0,0 +1,100 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.utils; + +import com.intellij.psi.*; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.Query; +import com.sixrr.metrics.utils.TestUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author Aleksandr Chudov. + */ +public class FieldUsageMapImpl implements FieldUsageMap { + private final Map, Set> fieldUsagePointMap = + new HashMap, Set>(1024); + private final Map, Set> fieldTestUsagePointMap = + new HashMap, Set>(1024); + private final Map, Set> fieldProductUsagePointMap = + new HashMap, Set>(1024); + + @NotNull + @Override + public Set calculateFieldUsagePoints(PsiField field) { + return getUsages(fieldUsagePointMap, field); + } + + @NotNull + @Override + public Set calculateTestFieldUsagePoints(PsiField field) { + return getUsages(fieldTestUsagePointMap, field); + } + + @NotNull + @Override + public Set calculateProductFieldUsagePoints(PsiField field) { + return getUsages(fieldProductUsagePointMap, field); + } + + private Set getUsages(Map, Set> map, PsiField field) { + final SmartPsiElementPointer pointer = getPointer(field); + if (!map.containsKey(pointer)) { + calculateUsages(field); + } + return map.get(pointer); + } + + @NotNull + private SmartPsiElementPointer getPointer(PsiField field) { + final SmartPointerManager manager = SmartPointerManager.getInstance(field.getProject()); + return manager.createSmartPsiElementPointer(field); + } + + private void calculateUsages(PsiField field) { + final Set allUsages = new HashSet(); + final Set testUsages = new HashSet(); + final Set productUsages = new HashSet(); + + final Query query = ReferencesSearch.search(field); + for (final PsiReference reference : query) { + final PsiElement element = reference.getElement(); + + final PsiClass referenceClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); + if (referenceClass == null) { + continue; + } + allUsages.add(reference); + if (TestUtils.isTest(referenceClass)) { + testUsages.add(reference); + } + if (TestUtils.isProduction(referenceClass)) { + productUsages.add(reference); + } + } + final SmartPsiElementPointer pointer = getPointer(field); + fieldUsagePointMap.put(pointer, allUsages); + fieldTestUsagePointMap.put(pointer, testUsages); + fieldProductUsagePointMap.put(pointer, productUsages); + } +} From e17ec6a6a3564935366e2bc2c667ed1c697d3daf Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Tue, 2 May 2017 15:43:02 +0300 Subject: [PATCH 11/18] Added calculating field usages in fan class metric --- .../classCalculators/FanClassCalculator.java | 53 +++++++++++++++++++ .../FanInClassCalculator.java | 28 ++++++---- .../FanOutClassCalculator.java | 40 +++++++++----- 3 files changed, 98 insertions(+), 23 deletions(-) create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanClassCalculator.java diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanClassCalculator.java new file mode 100644 index 0000000..652ee51 --- /dev/null +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanClassCalculator.java @@ -0,0 +1,53 @@ +/* + * Copyright 2005-2017 Sixth and Red River Software, Bas Leijdekkers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sixrr.stockmetrics.classCalculators; + +import com.intellij.openapi.util.Key; +import com.intellij.psi.PsiClass; +import com.sixrr.metrics.Metric; +import com.sixrr.metrics.MetricsExecutionContext; +import com.sixrr.metrics.MetricsResultsHolder; +import com.sixrr.stockmetrics.utils.FieldUsageMap; +import com.sixrr.stockmetrics.utils.FieldUsageMapImpl; + +import java.util.*; + +/** + * @author Aleksandr Chudov. + */ +public abstract class FanClassCalculator extends ClassCalculator { + protected final Map> metrics = new HashMap>(); + protected final Collection visitedClasses = new ArrayList(); + protected final Key fieldUsageKey = new Key("FieldUsageMap"); + + @Override + public void beginMetricsRun(Metric metric, MetricsResultsHolder resultsHolder, MetricsExecutionContext executionContext) { + final FieldUsageMap map = executionContext.getUserData(fieldUsageKey); + if(map == null) { + executionContext.putUserData(fieldUsageKey, new FieldUsageMapImpl()); + } + super.beginMetricsRun(metric, resultsHolder, executionContext); + } + + @Override + public void endMetricsRun() { + for (final PsiClass aClass : visitedClasses) { + postMetric(aClass, metrics.get(aClass).size()); + } + super.endMetricsRun(); + } +} diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java index 28564c4..dab6e75 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java @@ -17,6 +17,8 @@ package com.sixrr.stockmetrics.classCalculators; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.sixrr.stockmetrics.utils.FieldUsageMap; import java.util.ArrayList; import java.util.Collection; @@ -29,9 +31,7 @@ /** * @author Aleksandr Chudov. */ -public class FanInClassCalculator extends ClassCalculator { - private final Map> metrics = new HashMap>(); - private final Collection visitedClasses = new ArrayList(); +public class FanInClassCalculator extends FanClassCalculator { private final Stack classes = new Stack(); @Override @@ -39,14 +39,6 @@ protected PsiElementVisitor createVisitor() { return new Visitor(); } - @Override - public void endMetricsRun() { - for (PsiClass aClass : visitedClasses) { - postMetric(aClass, metrics.get(aClass).size()); - } - super.endMetricsRun(); - } - private class Visitor extends JavaRecursiveElementVisitor { @Override public void visitClass(PsiClass aClass) { @@ -57,6 +49,20 @@ public void visitClass(PsiClass aClass) { visitedClasses.add(aClass); super.visitClass(aClass); classes.pop(); + final FieldUsageMap map = executionContext.getUserData(fieldUsageKey); + final PsiField[] fields = aClass.getFields(); + for (final PsiField field : fields) { + final Set references = map.calculateFieldUsagePoints(field); + for (final PsiReference reference : references) { + final PsiElement element = reference.getElement(); + final PsiClass fieldClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); + if (fieldClass == null || fieldClass.equals(aClass)) { + continue; + } + final Set classes = metrics.get(aClass); + classes.add(fieldClass); + } + } } @Override diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java index 892bb8f..1010407 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java @@ -16,7 +16,16 @@ package com.sixrr.stockmetrics.classCalculators; +import com.intellij.openapi.util.Key; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.sixrr.metrics.Metric; +import com.sixrr.metrics.MetricsExecutionContext; +import com.sixrr.metrics.MetricsResultsHolder; +import com.sixrr.stockmetrics.utils.FieldUsageMap; +import com.sixrr.stockmetrics.utils.FieldUsageMapImpl; +import com.sixrr.stockmetrics.utils.MethodCallMap; +import com.sixrr.stockmetrics.utils.MethodCallMapImpl; import java.util.ArrayList; import java.util.Collection; @@ -29,9 +38,7 @@ /** * @author Aleksandr Chudov. */ -public class FanOutClassCalculator extends ClassCalculator { - private final Map> metrics = new HashMap>(); - private final Collection visitedClasses = new ArrayList(); +public class FanOutClassCalculator extends FanClassCalculator { private final Stack classes = new Stack(); @Override @@ -39,23 +46,32 @@ protected PsiElementVisitor createVisitor() { return new Visitor(); } - @Override - public void endMetricsRun() { - for (final PsiClass aClass : visitedClasses) { - postMetric(aClass, metrics.get(aClass).size()); - } - super.endMetricsRun(); - } - private class Visitor extends JavaRecursiveElementVisitor { @Override public void visitClass(PsiClass aClass) { - metrics.put(aClass, new HashSet()); + if (!metrics.containsKey(aClass)) { + metrics.put(aClass, new HashSet()); + } classes.push(aClass); visitedClasses.add(aClass); super.visitClass(aClass); classes.pop(); + final FieldUsageMap map = executionContext.getUserData(fieldUsageKey); + final PsiField[] fields = aClass.getFields(); + for (final PsiField field : fields) { + final Set references = map.calculateFieldUsagePoints(field); + for (final PsiReference reference : references) { + final PsiElement element = reference.getElement(); + final PsiClass fieldClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); + if (fieldClass == null || fieldClass.equals(aClass)) { + continue; + } + final Set s = metrics.containsKey(fieldClass) ? metrics.get(fieldClass) : new HashSet(); + s.add(aClass); + metrics.put(fieldClass, s); + } + } } @Override From 19c65d441776ed153346b248d66a2f2967ed3904 Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Thu, 11 May 2017 12:43:31 +0300 Subject: [PATCH 12/18] Now fan class metrics calculate metrics only for concrete classes --- .../stockmetrics/classCalculators/FanInClassCalculator.java | 3 +++ .../stockmetrics/classCalculators/FanOutClassCalculator.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java index dab6e75..1c61470 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java @@ -42,6 +42,9 @@ protected PsiElementVisitor createVisitor() { private class Visitor extends JavaRecursiveElementVisitor { @Override public void visitClass(PsiClass aClass) { + if (!isConcreteClass(aClass)) { + return; + } if (!metrics.containsKey(aClass)) { metrics.put(aClass, new HashSet()); } diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java index 1010407..46ac39b 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java @@ -50,6 +50,9 @@ private class Visitor extends JavaRecursiveElementVisitor { @Override public void visitClass(PsiClass aClass) { + if (!isConcreteClass(aClass)) { + return; + } if (!metrics.containsKey(aClass)) { metrics.put(aClass, new HashSet()); } From 919dda18106a374f94889bb0c97b8dd626344d20 Mon Sep 17 00:00:00 2001 From: Aleksandr Chudov Date: Thu, 11 May 2017 13:27:15 +0300 Subject: [PATCH 13/18] Now fan metrics ignore lambda methods --- .../stockmetrics/classCalculators/FanInClassCalculator.java | 4 ++++ .../classCalculators/FanOutClassCalculator.java | 4 ++++ .../methodCalculators/FanInMethodCalculator.java | 4 ++++ .../methodCalculators/FanOutMethodCalculator.java | 6 ++++++ 4 files changed, 18 insertions(+) diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java index 1c61470..2b865b6 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanInClassCalculator.java @@ -68,6 +68,10 @@ public void visitClass(PsiClass aClass) { } } + @Override + public void visitLambdaExpression(PsiLambdaExpression expression) { + } + @Override public void visitCallExpression(PsiCallExpression callExpression) { super.visitCallExpression(callExpression); diff --git a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java index 46ac39b..e9493ad 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/classCalculators/FanOutClassCalculator.java @@ -77,6 +77,10 @@ public void visitClass(PsiClass aClass) { } } + @Override + public void visitLambdaExpression(PsiLambdaExpression expression) { + } + @Override public void visitCallExpression(PsiCallExpression callExpression) { super.visitCallExpression(callExpression); diff --git a/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java index 32aea4a..ef18dc6 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanInMethodCalculator.java @@ -53,6 +53,10 @@ public void visitMethod(PsiMethod method) { methods.pop(); } + @Override + public void visitLambdaExpression(PsiLambdaExpression expression) { + } + @Override public void visitCallExpression(PsiCallExpression callExpression) { super.visitCallExpression(callExpression); diff --git a/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java index 2706bab..e4b22d8 100644 --- a/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java +++ b/stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/FanOutMethodCalculator.java @@ -17,7 +17,9 @@ package com.sixrr.stockmetrics.methodCalculators; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.sixrr.metrics.utils.BucketedCount; +import com.sixrr.metrics.utils.MethodUtils; import java.util.ArrayList; import java.util.Collection; @@ -53,6 +55,10 @@ public void visitMethod(PsiMethod method) { methods.pop(); } + @Override + public void visitLambdaExpression(PsiLambdaExpression expression) { + } + @Override public void visitCallExpression(PsiCallExpression callExpression) { super.visitCallExpression(callExpression); From b26b48220a7796cbd81eb5ae4ca62a871effc7d0 Mon Sep 17 00:00:00 2001 From: ArgentumWalker Date: Fri, 16 Jun 2017 18:39:26 +0300 Subject: [PATCH 14/18] Add DIT metric --- MetricsReloaded.ipr | 13 +--- .../metrics/plugin/ProjectMetricsAction.java | 2 + .../stockmetrics/JavaMetricProvider.java | 1 + .../i18n/StockMetricsBundle.properties | 2 + .../DepthInInheritanceMethodCalculator.java | 66 ++++++++++++++++ .../DepthInheritanceMethodMetric.java | 50 ++++++++++++ .../utils/ProjectContainerUtil.java | 78 +++++++++++++++++++ 7 files changed, 200 insertions(+), 12 deletions(-) create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/methodCalculators/DepthInInheritanceMethodCalculator.java create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/methodMetrics/DepthInheritanceMethodMetric.java create mode 100644 stockmetrics/src/com/sixrr/stockmetrics/utils/ProjectContainerUtil.java diff --git a/MetricsReloaded.ipr b/MetricsReloaded.ipr index 34610f3..43ab6b0 100644 --- a/MetricsReloaded.ipr +++ b/MetricsReloaded.ipr @@ -55,7 +55,6 @@