| 1 | package org.etsi.t3q.visitor; |
|---|
| 2 | |
|---|
| 3 | import java.util.ArrayList; |
|---|
| 4 | import java.util.Iterator; |
|---|
| 5 | import java.util.List; |
|---|
| 6 | import java.util.Map; |
|---|
| 7 | import java.util.Map.Entry; |
|---|
| 8 | import java.util.regex.Matcher; |
|---|
| 9 | import java.util.regex.Pattern; |
|---|
| 10 | |
|---|
| 11 | import org.etsi.common.MiscTools; |
|---|
| 12 | import org.etsi.common.logging.LoggingInterface.MessageClass; |
|---|
| 13 | import org.etsi.t3q.T3Q; |
|---|
| 14 | |
|---|
| 15 | import de.ugoe.cs.swe.trex.core.analyzer.astutil.ReferenceFinder; |
|---|
| 16 | import de.ugoe.cs.swe.trex.core.analyzer.astutil.ReferenceWithContext; |
|---|
| 17 | import de.ugoe.cs.swe.trex.core.analyzer.rfparser.LocationAST; |
|---|
| 18 | import de.ugoe.cs.swe.trex.core.analyzer.rfparser.TTCN3ParserTokenTypes; |
|---|
| 19 | import de.ugoe.cs.swe.trex.core.analyzer.rfparser.symboltable.Symbol; |
|---|
| 20 | |
|---|
| 21 | public class QualityCheckerExtras extends QualityChecker { |
|---|
| 22 | |
|---|
| 23 | public QualityCheckerExtras(T3QVisitor visitor) { |
|---|
| 24 | super(visitor); |
|---|
| 25 | // TODO Auto-generated constructor stub |
|---|
| 26 | } |
|---|
| 27 | |
|---|
| 28 | |
|---|
| 29 | public void checkZeroReferencedTestCases(LocationAST node) { |
|---|
| 30 | if (node.getFirstChild().getType() != TTCN3ParserTokenTypes.TestcaseDef){ |
|---|
| 31 | return; |
|---|
| 32 | } |
|---|
| 33 | ArrayList<LocationAST> identifiersList = LocationAST.getModuleDefinitionIdentifiersList(node); |
|---|
| 34 | LocationAST identifierNode = null; |
|---|
| 35 | String identifierText = null; |
|---|
| 36 | for (int i = 0; i < identifiersList.size(); i++){ |
|---|
| 37 | identifierNode = identifiersList.get(i); |
|---|
| 38 | identifierText = identifierNode.getFirstChild().getText(); |
|---|
| 39 | |
|---|
| 40 | Symbol s = identifierNode.getFirstChild().getSymbol(); |
|---|
| 41 | //TODO: add safety check here |
|---|
| 42 | if (getReferenceFinder().countReferences(s) == 0){ |
|---|
| 43 | //TODO: add stats counters |
|---|
| 44 | //TODO: add type information |
|---|
| 45 | //TODO: groups shall probably be excluded |
|---|
| 46 | this.getLoggingInterface().logWarning(identifierNode.getLine(), |
|---|
| 47 | identifierNode.getEndLine(), |
|---|
| 48 | MessageClass.LOGGING, |
|---|
| 49 | "Testcase definition for \""+identifierText+"\" is never used!", |
|---|
| 50 | MiscTools.getMethodName()); |
|---|
| 51 | } |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | } |
|---|
| 55 | |
|---|
| 56 | public void checkSetVerdictPrecededByLog(LocationAST node) { |
|---|
| 57 | //TODO: duplicated and combined constraints (presence and content according to context) |
|---|
| 58 | // Fixed: currently based on SetLocalVerdict node, |
|---|
| 59 | // consider starting at the fail or inconc node instead, checking |
|---|
| 60 | // whether it is |
|---|
| 61 | // within a set verdict context and proceed from there |
|---|
| 62 | // fix: it is specific to the set verdict and not to inconc or fail |
|---|
| 63 | // alone |
|---|
| 64 | boolean problemOccured = false; |
|---|
| 65 | String warning = ""; |
|---|
| 66 | if (node.getFirstChild().getType() == TTCN3ParserTokenTypes.Fail){ |
|---|
| 67 | LocationAST functionStatementOrDefNode = LocationAST.resolveParentsUntilType(node, TTCN3ParserTokenTypes.FunctionStatement); |
|---|
| 68 | LocationAST parentNode = functionStatementOrDefNode.getParent(); |
|---|
| 69 | LocationAST siblingNode = parentNode.getFirstChild(); |
|---|
| 70 | LocationAST prevSiblingNode = null; |
|---|
| 71 | do { |
|---|
| 72 | if (siblingNode.getType()!=TTCN3ParserTokenTypes.SemiColon){ |
|---|
| 73 | prevSiblingNode = siblingNode; |
|---|
| 74 | } |
|---|
| 75 | siblingNode = siblingNode.getNextSibling(); |
|---|
| 76 | } while ((siblingNode != functionStatementOrDefNode) && (siblingNode !=null)); |
|---|
| 77 | |
|---|
| 78 | if (prevSiblingNode!=null && prevSiblingNode.getType()==TTCN3ParserTokenTypes.FunctionStatement){ |
|---|
| 79 | if (prevSiblingNode.getNthChild(3).getType()!=TTCN3ParserTokenTypes.LogStatement){ |
|---|
| 80 | problemOccured = true; |
|---|
| 81 | warning = "Failing verdict not preceded by a log statement"; |
|---|
| 82 | } else { |
|---|
| 83 | //check log statement format according to context |
|---|
| 84 | LocationAST moduleDefinitionNode = LocationAST.resolveParentsUntilType(node, TTCN3ParserTokenTypes.ModuleDefinition); |
|---|
| 85 | if (moduleDefinitionNode.getFirstChild().getType()==TTCN3ParserTokenTypes.AltstepDef){ |
|---|
| 86 | LocationAST altstepDefIdentifierNode = moduleDefinitionNode.getNthChild(3); |
|---|
| 87 | |
|---|
| 88 | //CHECK REFERENCING CONTEXTS |
|---|
| 89 | int activatedAsDefault = 0; |
|---|
| 90 | boolean mixedContext = false; |
|---|
| 91 | Symbol altstepDefSymbol = altstepDefIdentifierNode.getSymbol(); |
|---|
| 92 | |
|---|
| 93 | Map<String, List<ReferenceWithContext>> referenceMap = getReferenceFinder() |
|---|
| 94 | .findReferences(altstepDefSymbol); |
|---|
| 95 | if (referenceMap.isEmpty()) { |
|---|
| 96 | activatedAsDefault = -1; |
|---|
| 97 | } else { |
|---|
| 98 | Iterator<Entry<String, List<ReferenceWithContext>>> referenceMapIterator = referenceMap |
|---|
| 99 | .entrySet().iterator(); |
|---|
| 100 | |
|---|
| 101 | while (referenceMapIterator.hasNext()) { |
|---|
| 102 | Entry<String, List<ReferenceWithContext>> referenceEntry = referenceMapIterator |
|---|
| 103 | .next(); |
|---|
| 104 | Iterator<ReferenceWithContext> referenceIterator = referenceEntry |
|---|
| 105 | .getValue().iterator(); |
|---|
| 106 | while (referenceIterator.hasNext()) { |
|---|
| 107 | ReferenceWithContext referenceWithContext = referenceIterator |
|---|
| 108 | .next(); |
|---|
| 109 | LocationAST referenceNode = referenceWithContext |
|---|
| 110 | .getReferenceNode(); |
|---|
| 111 | //HERE |
|---|
| 112 | if (referenceNode.getNthParent(3).getType() != TTCN3ParserTokenTypes.ActivateOp) { |
|---|
| 113 | if (activatedAsDefault==1){ |
|---|
| 114 | mixedContext = true; |
|---|
| 115 | } |
|---|
| 116 | activatedAsDefault = -1; |
|---|
| 117 | } else { |
|---|
| 118 | if (activatedAsDefault==-1){ |
|---|
| 119 | mixedContext = true; |
|---|
| 120 | } |
|---|
| 121 | activatedAsDefault = 1; |
|---|
| 122 | } |
|---|
| 123 | } |
|---|
| 124 | } |
|---|
| 125 | } |
|---|
| 126 | if (mixedContext){ |
|---|
| 127 | this.getLoggingInterface().logInformation(node.getLine(), |
|---|
| 128 | node.getEndLine(), |
|---|
| 129 | MessageClass.LOGGING, |
|---|
| 130 | "Alstep \""+altstepDefIdentifierNode.getText()+"\" is used in mixed contexts (both activated as default and not), therefore the results for the correct log statement format may be unreliable!", |
|---|
| 131 | MiscTools.getMethodName()); |
|---|
| 132 | } |
|---|
| 133 | if (activatedAsDefault > 0){ |
|---|
| 134 | this.checkLogStatementFormat(prevSiblingNode.getNthChild(3),false); |
|---|
| 135 | } else { |
|---|
| 136 | this.checkLogStatementFormat(prevSiblingNode.getNthChild(3),true); |
|---|
| 137 | } |
|---|
| 138 | } |
|---|
| 139 | } |
|---|
| 140 | } else { |
|---|
| 141 | problemOccured = true; |
|---|
| 142 | warning = "Failing verdict not preceded by a log statement!"; |
|---|
| 143 | } |
|---|
| 144 | } |
|---|
| 145 | if (node.getFirstChild().getType() == TTCN3ParserTokenTypes.None){ |
|---|
| 146 | //TODO: DUPLICATE BLOCK |
|---|
| 147 | LocationAST functionStatementOrDefNode = LocationAST.resolveParentsUntilType(node, TTCN3ParserTokenTypes.FunctionStatement); |
|---|
| 148 | LocationAST parentNode = functionStatementOrDefNode.getParent(); |
|---|
| 149 | LocationAST siblingNode = parentNode.getFirstChild(); |
|---|
| 150 | LocationAST prevSiblingNode = null; |
|---|
| 151 | do { |
|---|
| 152 | if (siblingNode.getType()!=TTCN3ParserTokenTypes.SemiColon){ |
|---|
| 153 | prevSiblingNode = siblingNode; |
|---|
| 154 | } |
|---|
| 155 | siblingNode = siblingNode.getNextSibling(); |
|---|
| 156 | } while ((siblingNode != functionStatementOrDefNode) && (siblingNode !=null)); |
|---|
| 157 | |
|---|
| 158 | if (prevSiblingNode!=null && prevSiblingNode.getType()==TTCN3ParserTokenTypes.FunctionStatement){ |
|---|
| 159 | if (prevSiblingNode.getNthChild(3).getType()!=TTCN3ParserTokenTypes.LogStatement){ |
|---|
| 160 | problemOccured = true; |
|---|
| 161 | warning = "Verdict \"none\" not preceded by a log statement!"; |
|---|
| 162 | } else { |
|---|
| 163 | this.checkLogStatementFormat(prevSiblingNode.getNthChild(3),false); |
|---|
| 164 | } |
|---|
| 165 | } |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | |
|---|
| 169 | if (problemOccured) { |
|---|
| 170 | this.getLoggingInterface().logWarning(node.getLine(), |
|---|
| 171 | node.getEndLine(), |
|---|
| 172 | MessageClass.LOGGING, |
|---|
| 173 | warning, |
|---|
| 174 | MiscTools.getMethodName()); |
|---|
| 175 | } |
|---|
| 176 | |
|---|
| 177 | // boolean problemOccured = false; |
|---|
| 178 | // |
|---|
| 179 | // if (ASTUtil.findChild(node, TTCN3ParserTokenTypes.Fail) != null |
|---|
| 180 | // || ASTUtil.findChild(node, TTCN3ParserTokenTypes.Inconc) != null) { |
|---|
| 181 | // |
|---|
| 182 | // LocationAST parentNode = LocationAST.resolveParentsUntilType(node, |
|---|
| 183 | // TTCN3ParserTokenTypes.FunctionStatementOrDef); |
|---|
| 184 | // |
|---|
| 185 | // int functionStatementOrDefsVisited = visitor |
|---|
| 186 | // .getFunctionStatementOrDefNodes().size(); |
|---|
| 187 | // if (parentNode == visitor.getFunctionStatementOrDefNodes().get( |
|---|
| 188 | // functionStatementOrDefsVisited - 1)) { |
|---|
| 189 | // int i = functionStatementOrDefsVisited - 2; |
|---|
| 190 | // if (i > 0) { |
|---|
| 191 | // LocationAST next = null; |
|---|
| 192 | // // skip semicolons |
|---|
| 193 | // next = visitor.getFunctionStatementOrDefNodes().get(i) |
|---|
| 194 | // .getNextSibling(); |
|---|
| 195 | // while ((next != null) |
|---|
| 196 | // && (next.getType() == TTCN3ParserTokenTypes.SemiColon)) { |
|---|
| 197 | // next = next.getNextSibling(); |
|---|
| 198 | // } |
|---|
| 199 | // |
|---|
| 200 | // if (next == parentNode) { |
|---|
| 201 | // LocationAST resultNode = (LocationAST) ASTUtil |
|---|
| 202 | // .findChild(visitor |
|---|
| 203 | // .getFunctionStatementOrDefNodes() |
|---|
| 204 | // .get(i), |
|---|
| 205 | // TTCN3ParserTokenTypes.LogStatement); |
|---|
| 206 | // if (resultNode == null) { |
|---|
| 207 | // problemOccured = true; |
|---|
| 208 | // } |
|---|
| 209 | // } else { |
|---|
| 210 | // problemOccured = true; |
|---|
| 211 | // } |
|---|
| 212 | // } else { |
|---|
| 213 | // problemOccured = true; |
|---|
| 214 | // } |
|---|
| 215 | // } |
|---|
| 216 | // } |
|---|
| 217 | } |
|---|
| 218 | |
|---|
| 219 | public void checkLogStatementFormat(LocationAST node, boolean withVerificationPoint) { |
|---|
| 220 | boolean problemOccured = false; |
|---|
| 221 | String warning = ""; |
|---|
| 222 | String logItemText = ""; |
|---|
| 223 | |
|---|
| 224 | LocationAST logItem = node.getFirstChild(); |
|---|
| 225 | |
|---|
| 226 | do { |
|---|
| 227 | if (logItem.getFirstChild().getType()!=TTCN3ParserTokenTypes.TemplateInstance){ |
|---|
| 228 | logItemText += logItem.getFirstChild().getText(); |
|---|
| 229 | } else { |
|---|
| 230 | //TODO: attempt to perform resolution |
|---|
| 231 | logItemText += "<<VAR>>"; |
|---|
| 232 | } |
|---|
| 233 | logItem = logItem.getNextSibling(); |
|---|
| 234 | } while (logItem!=null && logItem.getType()==TTCN3ParserTokenTypes.LogItem); |
|---|
| 235 | |
|---|
| 236 | |
|---|
| 237 | Pattern logPattern = Pattern.compile(T3Q.activeProfile |
|---|
| 238 | .getLogFormatRegExp()); |
|---|
| 239 | Matcher logMatcher = logPattern.matcher(logItemText); |
|---|
| 240 | if (!logMatcher.matches()) { |
|---|
| 241 | problemOccured = true; |
|---|
| 242 | warning = "Invalid log format (\"" + logItemText + "\")!"; |
|---|
| 243 | } else if (logMatcher.group(1).equals("") && withVerificationPoint) { |
|---|
| 244 | problemOccured = true; |
|---|
| 245 | warning = "Invalid log format (\"" + logItemText + "\") - missing verification point!"; |
|---|
| 246 | } |
|---|
| 247 | if (problemOccured) { |
|---|
| 248 | this.getLoggingInterface().logWarning(node.getLine(), |
|---|
| 249 | node.getEndLine(), |
|---|
| 250 | MessageClass.LOGGING, |
|---|
| 251 | warning, |
|---|
| 252 | MiscTools.getMethodName()); |
|---|
| 253 | } |
|---|
| 254 | |
|---|
| 255 | } |
|---|
| 256 | |
|---|
| 257 | } |
|---|