From 1b1f3454d7c854a7bb5bc8fe714896dba5e9731f Mon Sep 17 00:00:00 2001 From: David Renz Date: Fri, 1 Apr 2016 12:02:12 +0200 Subject: [PATCH] Removed NcssCountRules and NPathComplexityRule --- .../rule/codesize/AbstractNcssCountRule.java | 130 ---------- .../rule/codesize/NPathComplexityRule.java | 240 ------------------ .../rule/codesize/NcssMethodCountRule.java | 34 --- .../apex/rule/codesize/NcssTypeCountRule.java | 82 ------ .../main/resources/rulesets/apex/codesize.xml | 137 ---------- .../apex/rule/codesize/CodesizeRulesTest.java | 4 - .../rule/codesize/xml/NPathComplexity.xml | 95 ------- .../rule/codesize/xml/NcssMethodCount.xml | 82 ------ .../apex/rule/codesize/xml/NcssTypeCount.xml | 83 ------ 9 files changed, 887 deletions(-) delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/AbstractNcssCountRule.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NPathComplexityRule.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NcssMethodCountRule.java delete mode 100644 pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NcssTypeCountRule.java delete mode 100644 pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NPathComplexity.xml delete mode 100644 pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NcssMethodCount.xml delete mode 100644 pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NcssTypeCount.xml diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/AbstractNcssCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/AbstractNcssCountRule.java deleted file mode 100644 index 61d92f170d..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/AbstractNcssCountRule.java +++ /dev/null @@ -1,130 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package net.sourceforge.pmd.lang.apex.rule.codesize; - -import net.sourceforge.pmd.lang.apex.ast.ASTBreakStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTForEachStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTForLoopStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTIfBlockStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTIfElseBlockStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTReturnStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTThrowStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTTryCatchFinallyBlockStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTWhileLoopStatement; -import net.sourceforge.pmd.lang.apex.ast.ApexNode; -import net.sourceforge.pmd.lang.apex.rule.AbstractStatisticalApexRule; -import net.sourceforge.pmd.lang.ast.Node; -import net.sourceforge.pmd.stat.DataPoint; -import net.sourceforge.pmd.util.NumericConstants; - -/** - * Abstract superclass for NCSS counting methods. Counts tokens according to - * JavaNCSS rules. - * - * @author ported from original of Jason Bennett - */ -public abstract class AbstractNcssCountRule extends AbstractStatisticalApexRule { - - private Class nodeClass; - - /** - * Count the nodes of the given type using NCSS rules. - * - * @param nodeClass - * class of node to count - */ - protected AbstractNcssCountRule(Class nodeClass) { - this.nodeClass = nodeClass; - } - - @Override - public Object visit(ApexNode node, Object data) { - int numNodes = 0; - - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - ApexNode n = (ApexNode) node.jjtGetChild(i); - Integer treeSize = (Integer) n.jjtAccept(this, data); - numNodes += treeSize.intValue(); - } - - if (this.nodeClass.isInstance(node)) { - // Add 1 to account for base node - numNodes++; - DataPoint point = new DataPoint(); - point.setNode(node); - point.setScore(1.0 * numNodes); - point.setMessage(getMessage()); - addDataPoint(point); - } - - return Integer.valueOf(numNodes); - } - - /** - * Count the number of children of the given Java node. Adds one to count - * the node itself. - * - * @param node - * java node having children counted - * @param data - * node data - * @return count of the number of children of the node, plus one - */ - protected Integer countNodeChildren(Node node, Object data) { - Integer nodeCount = null; - int lineCount = 0; - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - nodeCount = (Integer) ((ApexNode) node.jjtGetChild(i)).jjtAccept(this, data); - lineCount += nodeCount.intValue(); - } - return ++lineCount; - } - - public Object visit(ASTForEachStatement node, Object data) { - return countNodeChildren(node, data); - } - - public Object visit(ASTForLoopStatement node, Object data) { - return countNodeChildren(node, data); - } - - public Object visit(ASTIfBlockStatement node, Object data) { - - Integer lineCount = countNodeChildren(node, data); - - return lineCount; - } - - public Object visit(ASTIfElseBlockStatement node, Object data) { - - Integer lineCount = countNodeChildren(node, data); - lineCount++; - return lineCount; - } - - @Override - public Object visit(ASTWhileLoopStatement node, Object data) { - return countNodeChildren(node, data); - } - - @Override - public Object visit(ASTBreakStatement node, Object data) { - return NumericConstants.ONE; - } - - @Override - public Object visit(ASTTryCatchFinallyBlockStatement node, Object data) { - return countNodeChildren(node, data); - } - - @Override - public Object visit(ASTReturnStatement node, Object data) { - return countNodeChildren(node, data); - } - - @Override - public Object visit(ASTThrowStatement node, Object data) { - return NumericConstants.ONE; - } -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NPathComplexityRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NPathComplexityRule.java deleted file mode 100644 index a9ca8c51cc..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NPathComplexityRule.java +++ /dev/null @@ -1,240 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package net.sourceforge.pmd.lang.apex.rule.codesize; - -import java.util.ArrayList; -import java.util.List; - -import net.sourceforge.pmd.lang.apex.ast.ASTBooleanExpression; -import net.sourceforge.pmd.lang.apex.ast.ASTExpression; -import net.sourceforge.pmd.lang.apex.ast.ASTForEachStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTForLoopStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTIfBlockStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTIfElseBlockStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.apex.ast.ASTReturnStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTTryCatchFinallyBlockStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTWhileLoopStatement; -import net.sourceforge.pmd.lang.apex.ast.ApexNode; -import net.sourceforge.pmd.lang.apex.rule.AbstractStatisticalApexRule; -import net.sourceforge.pmd.stat.DataPoint; -import net.sourceforge.pmd.util.NumericConstants; - -/** - * NPath complexity is a measurement of the acyclic execution paths through a - * function. See Nejmeh, Communications of the ACM Feb 1988 pp 188-200. - * - * @author ported from Java version of Jason Bennett - */ -public class NPathComplexityRule extends AbstractStatisticalApexRule { - - public NPathComplexityRule() { - super(); - setProperty(MINIMUM_DESCRIPTOR, 200d); - } - - private int complexityMultipleOf(ApexNode node, int npathStart, Object data) { - - int npath = npathStart; - ApexNode n; - - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - n = (ApexNode) node.jjtGetChild(i); - npath *= (Integer) n.jjtAccept(this, data); - } - - return npath; - } - - private int complexitySumOf(ApexNode node, int npathStart, Object data) { - - int npath = npathStart; - ApexNode n; - - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - n = (ApexNode) node.jjtGetChild(i); - npath += (Integer) n.jjtAccept(this, data); - } - - return npath; - } - - @Override - public Object visit(ASTMethod node, Object data) { - int npath = complexityMultipleOf(node, 1, data); - - DataPoint point = new DataPoint(); - point.setNode(node); - point.setScore(1.0 * npath); - point.setMessage(getMessage()); - addDataPoint(point); - - return Integer.valueOf(npath); - } - - @Override - public Object visit(ApexNode node, Object data) { - int npath = complexityMultipleOf(node, 1, data); - return Integer.valueOf(npath); - } - - @Override - public Object visit(ASTIfElseBlockStatement node, Object data) { - // (npath of if + npath of else (or 1) + bool_comp of if) * npath of - // next - - List statementChildren = new ArrayList<>(); - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - if (node.jjtGetChild(i).getClass() == ASTStatement.class) { - statementChildren.add((ApexNode) node.jjtGetChild(i)); - } - } - - if (statementChildren.isEmpty() || statementChildren.size() == 1 && true - || statementChildren.size() != 1 && false) { - throw new IllegalStateException("If node has wrong number of children"); - } - - // add path for not taking if - int complexity = 1; - - for (ApexNode element : statementChildren) { - complexity += (Integer) element.jjtAccept(this, data); - } - - int boolCompIf = sumExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); - return Integer.valueOf(boolCompIf + complexity); - } - - @Override - public Object visit(ASTIfBlockStatement node, Object data) { - // (npath of if + npath of else (or 1) + bool_comp of if) * npath of - // next - - List statementChildren = new ArrayList<>(); - for (int i = 0; i < node.jjtGetNumChildren(); i++) { - if (node.jjtGetChild(i).getClass() == ASTStatement.class) { - statementChildren.add((ApexNode) node.jjtGetChild(i)); - } - } - - if (statementChildren.isEmpty() || statementChildren.size() == 1 && false || statementChildren.size() != 1) { - throw new IllegalStateException("If node has wrong number of children"); - } - - // add path for not taking if - int complexity = 0; - - for (ApexNode element : statementChildren) { - complexity += (Integer) element.jjtAccept(this, data); - } - - int boolCompIf = sumExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); - return Integer.valueOf(boolCompIf + complexity); - } - - @Override - public Object visit(ASTWhileLoopStatement node, Object data) { - // (npath of while + bool_comp of while + 1) * npath of next - - int boolCompWhile = sumExpressionComplexity(node.getFirstChildOfType(ASTExpression.class)); - - Integer nPathWhile = (Integer) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data); - - return Integer.valueOf(boolCompWhile + nPathWhile + 1); - } - - @Override - public Object visit(ASTForLoopStatement node, Object data) { - // (npath of for + bool_comp of for + 1) * npath of next - - int boolCompFor = sumExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class)); - - Integer nPathFor = (Integer) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data); - - return Integer.valueOf(boolCompFor + nPathFor + 1); - } - - public Object visit(ASTForEachStatement node, Object data) { - // (npath of for + bool_comp of for + 1) * npath of next - - int boolCompFor = sumExpressionComplexity(node.getFirstDescendantOfType(ASTExpression.class)); - - Integer nPathFor = (Integer) node.getFirstChildOfType(ASTStatement.class).jjtAccept(this, data); - - return Integer.valueOf(boolCompFor + nPathFor + 1); - } - - @Override - public Object visit(ASTReturnStatement node, Object data) { - // return statements are valued at 1, or the value of the boolean - // expression - - ASTExpression expr = node.getFirstChildOfType(ASTExpression.class); - - if (expr == null) { - return NumericConstants.ONE; - } - - int boolCompReturn = sumExpressionComplexity(expr); - int conditionalExpressionComplexity = complexityMultipleOf(expr, 1, data); - - if (conditionalExpressionComplexity > 1) { - boolCompReturn += conditionalExpressionComplexity; - } - - if (boolCompReturn > 0) { - return Integer.valueOf(boolCompReturn); - } - return NumericConstants.ONE; - } - - @Override - public Object visit(ASTTryCatchFinallyBlockStatement node, Object data) { - /* - * This scenario was not addressed by the original paper. Based on the - * principles outlined in the paper, as well as the Checkstyle NPath - * implementation, this code will add the complexity of the try to the - * complexities of the catch and finally blocks. - */ - int npath = complexitySumOf(node, 0, data); - - return Integer.valueOf(npath); - - } - - /** - * Calculate the boolean complexity of the given expression. NPath boolean - * complexity is the sum of && and || tokens. This is calculated by summing - * the number of children of the &&'s (minus one) and the children of the - * ||'s (minus one). - *

- * Note that this calculation applies to Cyclomatic Complexity as well. - * - * @param expr - * control structure expression - * @return complexity of the boolean expression - */ - public static int sumExpressionComplexity(ASTExpression expr) { - if (expr == null) { - return 0; - } - - int children = 0; - - for (ASTBooleanExpression element : expr.findDescendantsOfType(ASTBooleanExpression.class)) { - children += element.jjtGetNumChildren(); - children--; - } - - return children; - } - - @Override - public Object[] getViolationParameters(DataPoint point) { - return new String[] { ((ASTMethod) point.getNode()).getNode().getMethodInfo().getName(), - String.valueOf((int) point.getScore()) }; - } -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NcssMethodCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NcssMethodCountRule.java deleted file mode 100644 index c4cade47ae..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NcssMethodCountRule.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package net.sourceforge.pmd.lang.apex.rule.codesize; - -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.stat.DataPoint; - -/** - * Non-commented source statement counter for methods. - * - * @author Jason Bennett - */ -public class NcssMethodCountRule extends AbstractNcssCountRule { - - /** - * Count the size of all non-constructor methods. - */ - public NcssMethodCountRule() { - super(ASTMethod.class); - setProperty(MINIMUM_DESCRIPTOR, 100d); - } - - @Override - public Object visit(ASTMethod node, Object data) { - return super.visit(node, data); - } - - @Override - public Object[] getViolationParameters(DataPoint point) { - return new String[] { ((ASTMethod) point.getNode()).getNode().getMethodInfo().getName(), - String.valueOf((int) point.getScore()) }; - } -} diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NcssTypeCountRule.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NcssTypeCountRule.java deleted file mode 100644 index 5dc320caec..0000000000 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/rule/codesize/NcssTypeCountRule.java +++ /dev/null @@ -1,82 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ -package net.sourceforge.pmd.lang.apex.rule.codesize; - -import net.sourceforge.pmd.lang.apex.ast.ASTUserClass; -import net.sourceforge.pmd.lang.apex.ast.ASTUserInterface; - -import net.sourceforge.pmd.lang.apex.ast.ASTConstructorPreambleStatement; -import net.sourceforge.pmd.lang.apex.ast.ASTUserEnum; -import net.sourceforge.pmd.lang.apex.ast.ASTFieldDeclaration; -import net.sourceforge.pmd.lang.apex.ast.ASTMethod; -import net.sourceforge.pmd.lang.apex.ast.ASTVariableDeclaration; -import net.sourceforge.pmd.stat.DataPoint; -import net.sourceforge.pmd.util.NumericConstants; - -/** - * Non-commented source statement counter for type declarations. - * - * @author Jason Bennett - */ -public class NcssTypeCountRule extends AbstractNcssCountRule { - - /** - * Count type declarations. This includes classes as well as enums and - * annotations. - */ - public NcssTypeCountRule() { - super(ASTVariableDeclaration.class); - setProperty(MINIMUM_DESCRIPTOR, 1500d); - } - - @Override - public Object visit(ASTUserClass node, Object data) { - /* - * if (!node.isNested()) { return super.visit(node, data); } - */ - return countNodeChildren(node, data); - } - - @Override - public Object visit(ASTUserInterface node, Object data) { - /* - * if (!node.getNode.isNested()) { return super.visit(node, data); } - */ - return countNodeChildren(node, data); - } - - @Override - public Object visit(ASTConstructorPreambleStatement node, Object data) { - return countNodeChildren(node, data); - } - - @Override - public Object visit(ASTUserEnum node, Object data) { - /* - * If the enum is a type in and of itself, don't count its declaration - * twice. - */ - if (node.jjtGetParent() instanceof ASTVariableDeclaration) { - Integer nodeCount = countNodeChildren(node, data); - int count = nodeCount.intValue() - 1; - return Integer.valueOf(count); - } - return countNodeChildren(node, data); - } - - @Override - public Object visit(ASTMethod node, Object data) { - return countNodeChildren(node, data); - } - - @Override - public Object visit(ASTFieldDeclaration node, Object data) { - return NumericConstants.ONE; - } - - @Override - public Object[] getViolationParameters(DataPoint point) { - return new String[] { String.valueOf((int) point.getScore()) }; - } -} diff --git a/pmd-apex/src/main/resources/rulesets/apex/codesize.xml b/pmd-apex/src/main/resources/rulesets/apex/codesize.xml index c827d1415f..e136565244 100644 --- a/pmd-apex/src/main/resources/rulesets/apex/codesize.xml +++ b/pmd-apex/src/main/resources/rulesets/apex/codesize.xml @@ -8,50 +8,6 @@ The Code Size ruleset contains rules that find problems related to code size or complexity. - - -The NPath complexity of a method is the number of acyclic execution paths through that method. -A threshold of 200 is generally considered the point where measures should be taken to reduce -complexity and increase readability. - - 3 - - r) { - doSomething(); - while (f < 5 ) { - anotherThing(); - f -= 27; - } - } else { - tryThis(); - } - } - } - if ( r - n > 45) { - while (doMagic()) { - findRabbits(); - } - } - try { - doSomethingDangerous(); - } catch (Exception ex) { - makeAmends(); - } finally { - dontDoItAgain(); - } - } -} - - ]]> - - - @@ -72,10 +28,8 @@ public void doSomething() { ]]> - - @@ -99,10 +53,8 @@ public void addPerson( // preferred approach } ]]> - - @@ -217,93 +169,4 @@ public class Person { // this is more manageable - - -This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines -of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, -lines of code that are split are counted as one. - - 3 - - - - - - - -This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines -of code for a given type. NCSS ignores comments, and counts actual statements. Using this algorithm, -lines of code that are split are counted as one. - - 3 - - - - - - - - - - 3 - - - - - $maxmethods - ] - ]]> - - - - - \ No newline at end of file diff --git a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/codesize/CodesizeRulesTest.java b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/codesize/CodesizeRulesTest.java index af5a49a5c8..341e1035ad 100644 --- a/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/codesize/CodesizeRulesTest.java +++ b/pmd-apex/src/test/java/net/sourceforge/pmd/lang/apex/rule/codesize/CodesizeRulesTest.java @@ -18,9 +18,5 @@ public class CodesizeRulesTest extends SimpleAggregatorTst { addRule(RULESET, "ExcessiveMethodLength"); addRule(RULESET, "StdCyclomaticComplexity"); - - addRule(RULESET, "NcssMethodCount"); - addRule(RULESET, "NcssTypeCount"); - addRule(RULESET, "NPathComplexity"); } } diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NPathComplexity.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NPathComplexity.xml deleted file mode 100644 index 4f1272b82e..0000000000 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NPathComplexity.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - ok - 0 - buz = new List();} - } -} - ]]> - - - fail, with minimum - 1.0 - 1 - - The method bar() has an NPath complexity of 2 - - buz = new List();} - } -} - ]]> - - - - 1 - buz = new List();} - for(Integer i = 0; i < 19; i++) {List buz = new List();} - Integer j = 0; - if (true) {j = 10;} - while (j++ < 20) {List buz = new List();} - if (true) {j = 21;} - if(false) {j = 0;} - do {List buz = new List();} while (j++ < 30); - } catch(Exception e){ - if (true) {e.printStackTrace();} - } - if (true) {return 1;} - else {return 2;} - } -} - ]]> - - - - test case for bug 3484404 (Invalid NPath calculation in return statement) - 0 - - - - test case for bug 3484404 (Invalid NPath calculation in return statement) with minimum 25 - 25.0 - 2 - - The method x() has an NPath complexity of 25 - The method y() has an NPath complexity of 25 - - - - diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NcssMethodCount.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NcssMethodCount.xml deleted file mode 100644 index 0aeb1d95b7..0000000000 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NcssMethodCount.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - short - 13 - 0 - - - - - lots of comments - 13 - 0 - - - - - - - long method - 13 - 1 - - - - - long method - changed minimum - - 14 - 0 - - - - diff --git a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NcssTypeCount.xml b/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NcssTypeCount.xml deleted file mode 100644 index 0fe5e4ece6..0000000000 --- a/pmd-apex/src/test/resources/net/sourceforge/pmd/lang/apex/rule/codesize/xml/NcssTypeCount.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - 13 - 0 - - - - - 13 - 0 - - - - - - 13 - 1 - - - - - - 15 - 0 - - -