source: branches/t3e-tools/t3q/src/org/etsi/t3q/visitor/QualityChecker.java @ 16

Last change on this file since 16 was 16, checked in by phdmakk, 14 years ago

+ rt guideline prototype implementation

  • Property svn:mime-type set to text/plain
File size: 100.0 KB
Line 
1package org.etsi.t3q.visitor;
2
3import java.io.BufferedReader;
4
5import java.io.FileInputStream;
6import java.io.IOException;
7import java.io.InputStreamReader;
8import java.lang.reflect.Field;
9import java.util.ArrayList;
10import java.util.Arrays;
11import java.util.HashMap;
12import java.util.Iterator;
13import java.util.LinkedHashSet;
14import java.util.LinkedList;
15import java.util.List;
16import java.util.Map;
17import java.util.Stack;
18import java.util.Map.Entry;
19import java.util.regex.Matcher;
20import java.util.regex.Pattern;
21
22import org.etsi.common.MiscTools;
23import org.etsi.common.logging.LoggingInterface;
24import org.etsi.common.logging.LoggingInterface.MessageClass;
25import org.etsi.t3q.T3Q;
26import org.etsi.t3q.config.QualityCheckProfile;
27
28import antlr.collections.AST;
29
30
31import de.ugoe.cs.swe.trex.core.analyzer.astutil.ReferenceFinder;
32import de.ugoe.cs.swe.trex.core.analyzer.astutil.ReferenceWithContext;
33import de.ugoe.cs.swe.trex.core.analyzer.rfparser.ASTUtil;
34import de.ugoe.cs.swe.trex.core.analyzer.rfparser.LocationAST;
35import de.ugoe.cs.swe.trex.core.analyzer.rfparser.TTCN3ParserTokenTypes;
36import de.ugoe.cs.swe.trex.core.analyzer.rfparser.symboltable.AltstepSymbol;
37import de.ugoe.cs.swe.trex.core.analyzer.rfparser.symboltable.FunctionSymbol;
38import de.ugoe.cs.swe.trex.core.analyzer.rfparser.symboltable.Symbol;
39
40
41public class QualityChecker {
42       
43        private LoggingInterface logger = null;
44       
45        protected static final int LEVEL0 = 0;
46        protected T3QVisitor visitor = null;
47        ModuleContentsChecker moduleContentsChecker = new ModuleContentsChecker();
48
49        //TODO: consider unified approach to statistics
50        //TODO: consider extracting the whole identifier management concept
51        private int totalIdentifierCount = 0;
52        private int repeatedIdentifierCount = 0;
53        private HashMap<String, ArrayList<LocationAST>> moduleLevelIdentifiersMap = new HashMap<String, ArrayList<LocationAST>>();
54        private ArrayList<LocationAST> subsequentLogStatementNodes = new ArrayList<LocationAST>();
55        private Stack<LocationAST> cyclicFunctionReferences = new Stack<LocationAST>();
56       
57       
58        public QualityChecker(T3QVisitor visitor) {
59                this.visitor = visitor;
60                this.logger = new LoggingInterface(T3Q.activeProfile.getLoggingConfiguration());
61                this.logger.setMaximumLogLevel(T3Q.getLogLevel());
62        }
63       
64        public LoggingInterface getLoggingInterface(){
65                return this.logger;
66        }
67       
68        // -------------------------------------------------------------------------------------------
69        // This should serve as a base template - simply copy it with the
70        // appropriate name and change its contents
71        public void qualityCheckTemplate(LocationAST node) {
72                // Not explicitly necessary, for consistency only
73                boolean problemOccured = false;
74                problemOccured = true;
75                if (problemOccured) {
76                        String message = "<message>";
77                        this.getLoggingInterface().logWarning(node.getLine(), node.getEndLine(), MessageClass.UNIVERSAL, message);
78
79                }
80        }
81
82        // -------------------------------------------------------------------------------------------
83
84        private void addModuleLevelIdentifier(LocationAST identifierNode){
85                String identifierText = identifierNode.getFirstChild().getText();
86                if (!moduleLevelIdentifiersMap.containsKey(identifierText)){
87                        moduleLevelIdentifiersMap.put(identifierText, new ArrayList<LocationAST>());
88                }
89                moduleLevelIdentifiersMap.get(identifierText).add(identifierNode);
90        }
91               
92        // -------------------------------------------------------------------------------------------
93
94        // TODO: move to LocationAST?
95        // currently not used, it was supposed to replace the default equals method
96        // due to an error, but the error has been since fixed
97        private boolean isNodeEqualToNode(LocationAST node1, LocationAST node2) {
98                boolean nodesEqual = false;
99//              if ((node1.getType() == node2.getType())
100//                              && (node1.getOffset() == node2.getOffset())) {
101                if (node1 == node2){
102                        nodesEqual = true;
103                }
104
105                return nodesEqual;
106        }
107
108        // -------------------------------------------------------------------------------------------
109
110        public void stringLevelChecks(String filename) {
111                // TODO: document features
112                try {
113                        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
114                        String line = null;
115                        int lineNumber = 0;
116                        while ((line = br.readLine()) != null) {
117                                lineNumber++;
118                                if (T3Q.activeProfile.isCheckNoTabs()) {
119                                        if (line.contains("\t")) {
120                                                this.getLoggingInterface().logWarning(lineNumber,
121                                                                lineNumber,
122                                                                MessageClass.STYLE,
123                                                                "Line contains a tab character!",
124                                                                "at column " + line.indexOf("\t") + "");
125                                        }
126                                }
127                        }
128                } catch (IOException e) {
129                        e.printStackTrace();
130                }
131        }
132
133        // -------------------------------------------------------------------------------------------
134       
135        private boolean isNodeWithinGroup(LocationAST startNode,
136                        LocationAST targetGroupNode) {
137                boolean isNodeWithinGroup = false;
138                LocationAST groupDef = LocationAST.resolveParentsUntilType(startNode
139                                .getParent(), TTCN3ParserTokenTypes.GroupDef);
140                if (groupDef != null) {
141                        if (groupDef.equals(targetGroupNode)) {
142                                isNodeWithinGroup = true;
143                        } else {
144                                isNodeWithinGroup = isNodeWithinGroup(groupDef, targetGroupNode);
145                        }
146                }
147
148                return isNodeWithinGroup;
149        }
150
151        // -------------------------------------------------------------------------------------------
152
153        // Return value is boolean - true if function is used to start a behavior,
154        // false otherwise
155        private boolean isFunctionStartsBehavior(
156                        LocationAST functionDefIdentifierNode) {
157                boolean startsBehavior = true;
158                Symbol functionDefSymbol = functionDefIdentifierNode.getSymbol();
159
160                ReferenceFinder referenceFinder = new ReferenceFinder();
161                Map<String, List<ReferenceWithContext>> referenceMap = referenceFinder
162                                .findReferences(functionDefSymbol);
163                if (referenceMap.isEmpty()) {
164                        startsBehavior = false;
165                } else {
166                        Iterator<Entry<String, List<ReferenceWithContext>>> referenceMapIterator = referenceMap
167                                        .entrySet().iterator();
168
169                        while (referenceMapIterator.hasNext()) {
170                                Entry<String, List<ReferenceWithContext>> referenceEntry = referenceMapIterator
171                                                .next();
172                                Iterator<ReferenceWithContext> referenceIterator = referenceEntry
173                                                .getValue().iterator();
174                                while (referenceIterator.hasNext()) {
175                                        ReferenceWithContext referenceWithContext = referenceIterator
176                                                        .next();
177                                        LocationAST referenceNode = referenceWithContext
178                                                        .getReferenceNode();
179                                        //TODO: review getNthParent calls below!!!
180                                        if (referenceNode.getNthParent(4).getType() != TTCN3ParserTokenTypes.StartTCStatement) {
181                                                startsBehavior = false;
182                                        } else {
183                                                LocationAST startingEntityIdentifierNode = (LocationAST) ASTUtil
184                                                                .findChild(referenceNode.getNthParent(4),
185                                                                                TTCN3ParserTokenTypes.Identifier)
186                                                                .getFirstChild();
187
188                                                Symbol startingEntitySymbol = startingEntityIdentifierNode.getSymbol();
189                                                if (startingEntitySymbol.getDeclarationNode()
190                                                                .getNthParent(3).getType() == TTCN3ParserTokenTypes.TimerInstance) {
191                                                        startsBehavior = false;
192                                                }
193                                        }
194                                }
195                        }
196                }
197                return startsBehavior;
198        }
199
200        // -------------------------------------------------------------------------------------------
201
202        private boolean isReferenceWithinImport(LocationAST referenceNode){
203                boolean isReferenceWithinImport = false;
204                if (LocationAST.resolveParentsUntilType(referenceNode, TTCN3ParserTokenTypes.ImportDef) != null){
205                        isReferenceWithinImport = true;
206                }
207                return isReferenceWithinImport;
208        }
209
210        // -------------------------------------------------------------------------------------------
211
212        private boolean isReferenceWithinModule(
213                        LocationAST referenceNode, LocationAST moduleNode) {
214                boolean isReferenceWithinModule = false;
215               
216                LocationAST containingModuleNode = ASTUtil.getModuleNode(referenceNode);
217                if (isNodeEqualToNode(moduleNode, containingModuleNode)){
218                        isReferenceWithinModule = true;
219                }
220                return isReferenceWithinModule;
221        }
222
223       
224        // -------------------------------------------------------------------------------------------
225
226        private boolean isReferenceWithinModuleDefinition(
227                        LocationAST referenceNode, LocationAST moduleDefinitionNode) {
228                boolean isReferenceWithinModuleDefinition = false;
229                LocationAST containingModuleDefinitionNode = LocationAST.resolveParentsUntilType(referenceNode, TTCN3ParserTokenTypes.ModuleDefinition);
230                if (isNodeEqualToNode(moduleDefinitionNode, containingModuleDefinitionNode)){
231                        isReferenceWithinModuleDefinition = true;
232                }
233                return isReferenceWithinModuleDefinition;
234        }
235
236        // -------------------------------------------------------------------------------------------
237
238        // TODO: move to Symbol or LocationAST
239        private int getReferenceCountWithinModule(LocationAST identifierNode,
240                        LocationAST moduleNode) {
241                int referencesWithinCurrentModule = 0;
242                Symbol definitionSymbol = identifierNode
243                .getFirstChild().getSymbol();
244
245                if (definitionSymbol != null) {
246                        ArrayList<Symbol> relevantSymbols = new ArrayList<Symbol>();
247                        relevantSymbols.add(definitionSymbol);
248                        LocationAST moduleDefinitionNode = LocationAST.resolveParentsUntilType(definitionSymbol.getDeclarationNode(), TTCN3ParserTokenTypes.ModuleDefinition);
249                        LocationAST moduleDefinitionTypeNode = LocationAST.getModuleDefinitionTypeNode(moduleDefinitionNode);
250                        if (moduleDefinitionTypeNode.getType()==TTCN3ParserTokenTypes.TypeDef && ASTUtil.findChild(moduleDefinitionTypeNode, TTCN3ParserTokenTypes.EnumDef)!=null) {
251                                relevantSymbols.addAll(definitionSymbol.getScope().getSymbols().values());
252                        }
253                       
254                        ReferenceFinder referenceFinder = new ReferenceFinder();
255                        Map<String, List<ReferenceWithContext>> referenceMap = referenceFinder
256                                        .findReferences(relevantSymbols);
257                        Iterator<List<ReferenceWithContext>> referenceMapIterator = referenceMap
258                                        .values().iterator();
259                        while (referenceMapIterator.hasNext()) {
260                                Iterator<ReferenceWithContext> referenceIterator = referenceMapIterator
261                                                .next().iterator();
262                                while (referenceIterator.hasNext()) {
263
264                                        ReferenceWithContext referenceWithContext = referenceIterator
265                                                        .next();
266                                        LocationAST referenceNode = referenceWithContext
267                                                        .getReferenceNode();
268
269                                        if (!isReferenceWithinImport(referenceNode)) {
270                                                if (isReferenceWithinModule(referenceNode, moduleNode)) {
271                                                        referencesWithinCurrentModule++;
272                                                }
273                                        }
274                                }
275                        }
276                } else {
277                        //TODO: need handling
278                }
279
280                return referencesWithinCurrentModule;
281        }
282
283        // -------------------------------------------------------------------------------------------
284
285        //TODO: move to Symbol or LocationAST
286        private int getReferenceCountWithinModuleOrGroup(ArrayList<LocationAST> moduleOrGroupLevelIdentifiers, LocationAST moduleNode) {
287                int referencesWithinCurrentModuleOrGroup = 0;
288
289                for (LocationAST importedModuleDefinitionIdentifier : moduleOrGroupLevelIdentifiers){
290                        referencesWithinCurrentModuleOrGroup += getReferenceCountWithinModule(
291                                                importedModuleDefinitionIdentifier, moduleNode);
292                }
293                return referencesWithinCurrentModuleOrGroup;
294        }
295       
296        // -------------------------------------------------------------------------------------------
297        //TODO: may be deprecated
298        private boolean isIdentifierWithinAllWithExcept(LocationAST identifierNode) {
299                boolean isIdentifierWithinAllWithExcept = false;
300                int[] exceptTypeNodes = {
301                                TTCN3ParserTokenTypes.AllAltstepsWithExcept,
302                                TTCN3ParserTokenTypes.AllTestcasesWithExcept,
303                                TTCN3ParserTokenTypes.AllConstsWithExcept,
304                                TTCN3ParserTokenTypes.AllFunctionsWithExcept,
305                                TTCN3ParserTokenTypes.AllModuleParWithExcept,
306                                TTCN3ParserTokenTypes.AllSignaturesWithExcept,
307                                TTCN3ParserTokenTypes.AllTemplsWithExcept,
308                                TTCN3ParserTokenTypes.AllTypesWithExcept,
309                                TTCN3ParserTokenTypes.AllGroupsWithExcept};
310                if (LocationAST.resolveParentsUntilType(identifierNode, exceptTypeNodes) != null){
311                        isIdentifierWithinAllWithExcept = true;
312                }
313                return isIdentifierWithinAllWithExcept;
314        }
315       
316        // -------------------------------------------------------------------------------------------
317
318        /**
319         * @param importElementNode - import element node
320         * @return true if the import element is non-specific (has an all keyword), false otherwise
321         */
322       
323        private boolean isImportElementNonSpecific(LocationAST importElementNode) {
324                boolean isImportElementNonSpecific = false;
325                List<Integer> nodeTypes =  Arrays.asList(
326                                TTCN3ParserTokenTypes.AllAltstepsWithExcept,
327                                TTCN3ParserTokenTypes.AllTestcasesWithExcept,
328                                TTCN3ParserTokenTypes.AllConstsWithExcept,
329                                TTCN3ParserTokenTypes.AllFunctionsWithExcept,
330                                TTCN3ParserTokenTypes.AllModuleParWithExcept,
331                                TTCN3ParserTokenTypes.AllSignaturesWithExcept,
332                                TTCN3ParserTokenTypes.AllTemplsWithExcept,
333                                TTCN3ParserTokenTypes.AllTypesWithExcept,
334                                TTCN3ParserTokenTypes.AllGroupsWithExcept);
335               
336                if (nodeTypes.contains(importElementNode.getNthChild(2).getType())){
337                        isImportElementNonSpecific = true;
338                }
339                return isImportElementNonSpecific;
340        }
341       
342        // -------------------------------------------------------------------------------------------
343
344        /**
345         * @param importElementNode - import element node
346         * @return type of the corresponding module definition
347         */
348       
349        private int getCorrespondingModuleDefinitionType(LocationAST importElementNode) {
350                //TODO: duplicated, sort out
351                int correspondingType = 0;
352                switch (importElementNode.getNthChild(2).getType()) {
353                case TTCN3ParserTokenTypes.AllAltstepsWithExcept:
354                case TTCN3ParserTokenTypes.AltstepRefList:
355                        correspondingType = TTCN3ParserTokenTypes.AltstepDef;
356                        break;
357                case TTCN3ParserTokenTypes.AllTestcasesWithExcept:
358                case TTCN3ParserTokenTypes.TestcaseRefList:
359                        correspondingType = TTCN3ParserTokenTypes.TestcaseDef;
360                        break;
361                case TTCN3ParserTokenTypes.AllConstsWithExcept:
362                case TTCN3ParserTokenTypes.ConstRefList:
363                        correspondingType = TTCN3ParserTokenTypes.ConstDef;
364                        break;
365                case TTCN3ParserTokenTypes.AllFunctionsWithExcept:
366                case TTCN3ParserTokenTypes.FunctionRefList:
367                        correspondingType = TTCN3ParserTokenTypes.FunctionDef;
368                        break;
369                case TTCN3ParserTokenTypes.AllModuleParWithExcept:
370                case TTCN3ParserTokenTypes.ModuleParRefList:
371                        correspondingType = TTCN3ParserTokenTypes.ModuleParDef;
372                        break;
373                case TTCN3ParserTokenTypes.AllSignaturesWithExcept:
374                case TTCN3ParserTokenTypes.SignatureRefList:
375                        correspondingType = TTCN3ParserTokenTypes.SignatureDef;
376                        break;
377                case TTCN3ParserTokenTypes.AllTemplsWithExcept:
378                case TTCN3ParserTokenTypes.TemplateRefList:
379                        correspondingType = TTCN3ParserTokenTypes.TemplateDef;
380                        break;
381                case TTCN3ParserTokenTypes.AllTypesWithExcept:
382                case TTCN3ParserTokenTypes.TypeRefList:
383                        correspondingType = TTCN3ParserTokenTypes.TypeDef;
384                        break;
385                case TTCN3ParserTokenTypes.AllGroupsWithExcept:
386                case TTCN3ParserTokenTypes.GroupRefListWithExcept:
387                        correspondingType = TTCN3ParserTokenTypes.GroupDef;
388                        break;
389                default:
390                        break;
391                }
392                return correspondingType;
393        }
394
395        // -------------------------------------------------------------------------------------------
396
397        public void checkNoUnusedLocalDefinitions(LocationAST node) {
398                ArrayList<LocationAST> localDefinitionsIdentifiersList = LocationAST.getLocalDefinitionsIdentifiersList(node);
399                if (localDefinitionsIdentifiersList == null) {
400                        return; //irrelevant type of module definition!
401                }
402               
403                ReferenceFinder referenceFinder = new ReferenceFinder();
404                String moduleDefinitionIdentifierText;
405                if (node.getType()!=TTCN3ParserTokenTypes.ModuleDefinition) {
406                        moduleDefinitionIdentifierText = "Module Control Part";
407                } else {
408                        moduleDefinitionIdentifierText = LocationAST.getModuleDefinitionIdentifiersList(node).get(0).getFirstChild().getText();
409                }
410                for (LocationAST localDefinitionIdentifier : localDefinitionsIdentifiersList) {
411                        Symbol symbol = localDefinitionIdentifier.getFirstChild().getSymbol();
412                        if (referenceFinder.countReferences(symbol)==0) {
413                                this.getLoggingInterface().logWarning(localDefinitionIdentifier.getLine(),
414                                                localDefinitionIdentifier.getEndLine(),
415                                                MessageClass.STYLE,
416                                                "Local definition for \""+localDefinitionIdentifier.getFirstChild().getText()+"\" in definition of \""+moduleDefinitionIdentifierText+"\" is never used!",
417                                                "6.11, " + MiscTools.getMethodName());
418                        }
419                }
420        }
421       
422        // -------------------------------------------------------------------------------------------
423
424        public void checkNoLiterals(LocationAST node) {
425                // TODO: matching symbols too? boolean values too? verdicts, omits,
426                // enums and addresses too?
427                boolean problemOccured = false;
428                switch (node.getFirstChild().getType()) {
429                case TTCN3ParserTokenTypes.BitStringValue:
430                case TTCN3ParserTokenTypes.CharStringValue:
431                case TTCN3ParserTokenTypes.IntegerValue:
432                case TTCN3ParserTokenTypes.OctetStringValue:
433                case TTCN3ParserTokenTypes.HexStringValue:
434                case TTCN3ParserTokenTypes.FloatValue:
435                        // TODO: what about inline templates?
436                        LocationAST containingModuleDefinition = LocationAST.resolveParentsUntilType(node,
437                                        new int[] { TTCN3ParserTokenTypes.ModuleParDef,
438                                                        TTCN3ParserTokenTypes.TemplateDef,
439                                                        TTCN3ParserTokenTypes.ConstDef });
440                        if (containingModuleDefinition == null) {
441                                problemOccured = true;
442                        }
443                }
444                if (problemOccured) {
445                        this.getLoggingInterface().logWarning(node.getLine(),
446                                        node.getEndLine(),
447                                        MessageClass.STYLE,
448                                        "Literal value is used!",
449                                        "6.12, " + MiscTools.getMethodName());
450                }
451
452        }
453        // -------------------------------------------------------------------------------------------
454
455        public void checkNoUnusedFormalParameters(LocationAST node) {
456                if (LocationAST.resolveParentsUntilType(node, TTCN3ParserTokenTypes.ExtFunctionDef)!=null) {
457                        return;
458                }
459
460                LocationAST identifierNode = (LocationAST) ASTUtil.findSibling(node.getFirstChild(), TTCN3ParserTokenTypes.Identifier);
461
462                //TODO: extract to a separate method
463                LocationAST TemplateDefNode = LocationAST.resolveParentsUntilType(node, TTCN3ParserTokenTypes.TemplateDef);
464                if (TemplateDefNode != null) {
465                        LocationAST derivedDefNode = ASTUtil.findDerivedDef(TemplateDefNode);
466                        if (derivedDefNode!=null) {
467                                Symbol symbol = derivedDefNode.getFirstChild().getFirstChild().getSymbol();
468                                if (symbol == null) {
469                                        this.getLoggingInterface().logInformation(node.getLine(),
470                                                        node.getEndLine(),
471                                                        MessageClass.LOGGING,
472                                                        "Template definition for \""
473                                                                        + derivedDefNode.getFirstChild().getFirstChild().getText()
474                                                                        + "\" cannot be resolved! It cannot be determined whether formal parameter \""+identifierNode.getFirstChild().getText()+"\" is used or not!",
475                                                        "6.11, " + MiscTools.getMethodName());
476                                        //SKIP
477                                        return;
478                                } else {
479                                        LocationAST declarationNode = symbol.getDeclarationNode();
480                                        List<AST> inheritedFormalParameters = ASTUtil.getFormalParameters(LocationAST.resolveParentsUntilType(declarationNode, TTCN3ParserTokenTypes.TemplateDef));
481                                        if (inheritedFormalParameters != null) {
482                                                for (AST inheritedFormalParameter : inheritedFormalParameters) {
483                                                        if (inheritedFormalParameter.getText().equals(identifierNode.getFirstChild().getText())) {
484                                                                //SKIP
485                                                                return;
486                                                        }
487                                                }
488                                        }
489                                }
490                        }
491                }
492               
493                Symbol formalParSymbol = identifierNode.getFirstChild().getSymbol();
494                ReferenceFinder referenceFinder = new ReferenceFinder();
495                int referenceCount = 0;
496                referenceCount = referenceFinder.countReferences(formalParSymbol);
497                if (referenceCount == 0) {
498                        String containingModuleDefinitionName = node.getContainingModuleDefinitionIdentifiersList().get(0).getFirstChild().getText();
499                        this.getLoggingInterface().logWarning(identifierNode.getLine(),
500                                        identifierNode.getEndLine(),
501                                        MessageClass.STYLE,
502                                        "Formal parameter \""
503                                                        + identifierNode.getFirstChild().getText()
504                                                        + "\" in definition for \""
505                                                        + containingModuleDefinitionName
506                                                        + "\" is never used!",
507                                        "6.11, " + MiscTools.getMethodName());
508                }
509
510        }
511
512        // -------------------------------------------------------------------------------------------
513        //TODO duplicated
514        public void listImportingModuleNames(LocationAST node) {
515                LocationAST moduleIdentifier = node.getNthChild(3);
516                Symbol moduleSymbol = moduleIdentifier.getFirstChild().getSymbol();
517
518                ReferenceFinder referenceFinder = new ReferenceFinder();
519                Map<String, List<ReferenceWithContext>> referenceMap = referenceFinder.findReferences(moduleSymbol);
520                Iterator<List<ReferenceWithContext>> referenceMapIterator = referenceMap.values().iterator();
521                while (referenceMapIterator.hasNext()) {
522                        Iterator<ReferenceWithContext> referenceIterator = referenceMapIterator.next().iterator();
523                        while (referenceIterator.hasNext()) {
524                                LocationAST referenceNode = referenceIterator.next().getReferenceNode();
525                                if (isReferenceWithinImport(referenceNode)) {
526                                        this.getLoggingInterface().logInformation(moduleIdentifier.getLine(),
527                                                        moduleIdentifier.getEndLine(),
528                                                        MessageClass.GENERAL,
529                                                        "Module \""
530                                                                        + moduleIdentifier.getFirstChild().getText()
531                                                                        + "\" is imported in module \""
532                                                                        + ASTUtil.getEnclosingModuleName(referenceNode)
533                                                                        + "\"!",
534                                                        "1.19, " + MiscTools.getMethodName());
535                                }
536                        }
537                }
538        }
539
540        // -------------------------------------------------------------------------------------------
541        //TODO: duplicated
542        public void listImportingModuleFileNames(LocationAST node) {
543                LocationAST moduleIdentifier = node.getNthChild(3);
544                Symbol moduleSymbol = moduleIdentifier.getFirstChild().getSymbol();
545
546                ReferenceFinder referenceFinder = new ReferenceFinder();
547                Map<String, List<ReferenceWithContext>> referenceMap = referenceFinder.findReferences(moduleSymbol);
548                Iterator<List<ReferenceWithContext>> referenceMapIterator = referenceMap.values().iterator();
549                while (referenceMapIterator.hasNext()) {
550                        Iterator<ReferenceWithContext> referenceIterator = referenceMapIterator.next().iterator();
551                        while (referenceIterator.hasNext()) {
552                                LocationAST referenceNode = referenceIterator.next().getReferenceNode();
553                                if (isReferenceWithinImport(referenceNode)) {
554                                        this.getLoggingInterface().logInformation(moduleIdentifier.getLine(),
555                                                        moduleIdentifier.getEndLine(),
556                                                        MessageClass.GENERAL,
557                                                        "Module \""
558                                                                        + moduleIdentifier.getFirstChild().getText()
559                                                                        + "\" is imported in module \""
560                                                                        + ASTUtil.getEnclosingModuleName(referenceNode)
561                                                                        + "\" located in \""
562                                                                        + referenceNode.getScope().getAssociatedFilename()
563                                                                        + "\"!",
564                                                        "1.19, " + MiscTools.getMethodName());
565                                }
566                        }
567                }
568        }
569
570       
571        // -------------------------------------------------------------------------------------------
572
573        public void listImportedModuleNames(LocationAST node) {
574                LocationAST importedModuleIdentifier = node.getNthChild(4);
575                this.getLoggingInterface().logInformation(importedModuleIdentifier.getLine(),
576                                importedModuleIdentifier.getEndLine(),
577                                MessageClass.GENERAL,
578                                "Importing from module \""
579                                                + importedModuleIdentifier.getFirstChild().getText()
580                                                + "\"...",
581                                "1.18, " + MiscTools.getMethodName());
582        }
583
584        // -------------------------------------------------------------------------------------------
585
586        public void listImportedModuleFileNames(LocationAST node) {
587                LocationAST importedModuleIdentifier = node.getNthChild(4);
588                Symbol importedModuleSymbol = importedModuleIdentifier.getFirstChild().getSymbol();
589                if (importedModuleSymbol == null) {
590                        // resolvable?
591                        this.getLoggingInterface().logInformation(importedModuleIdentifier.getLine(),
592                                        importedModuleIdentifier.getEndLine(),
593                                        MessageClass.GENERAL,
594                                        "Imported module \""
595                                                        + importedModuleIdentifier.getFirstChild().getText()
596                                                        + "\" cannot be resolved!",
597                                        "1.18, " + MiscTools.getMethodName());
598                        return;
599                }
600
601                this.getLoggingInterface().logInformation(importedModuleIdentifier.getLine(),
602                                importedModuleIdentifier.getEndLine(),
603                                MessageClass.GENERAL,
604                                "Importing from module \""
605                                                + importedModuleIdentifier.getFirstChild().getText()
606                                                + "\" located in \""
607                                                + importedModuleSymbol.getScope().getAssociatedFilename()
608                                                + "\"...",
609                                "1.18, " + MiscTools.getMethodName());
610        }
611
612       
613        // -------------------------------------------------------------------------------------------
614       
615        public void checkNoUnusedImports(LocationAST node) {
616                // TODO: Consider splitting further
617                LocationAST importedModuleIdentifier = (LocationAST) ASTUtil.findChild(node,
618                                TTCN3ParserTokenTypes.Identifier);
619                Symbol importedModuleSymbol = importedModuleIdentifier.getFirstChild().getSymbol();
620                if (importedModuleSymbol == null) {
621                        // resolvable?
622                        this.getLoggingInterface().logInformation(importedModuleIdentifier.getLine(),
623                                        importedModuleIdentifier.getEndLine(),
624                                        MessageClass.STYLE,
625                                        "Imported module \""
626                                                        + importedModuleIdentifier.getFirstChild().getText()
627                                                        + "\" cannot be resolved!",
628                                        "6.18, " + MiscTools.getMethodName());
629                        return;
630                }
631
632                LocationAST currentModuleNode = ASTUtil.getModuleNode(node);
633                LocationAST importedModuleNode = ASTUtil.getModuleNode(importedModuleSymbol.getDeclarationNode());
634
635                LocationAST importSpecNode = node.getFirstChild().getNextSibling();
636                if (importSpecNode.getType() == TTCN3ParserTokenTypes.AllWithExcepts) {
637                        // any reference?
638                        ArrayList<LocationAST> moduleLevelIdentifiers = LocationAST.getModuleOrGroupLevelIdentifiers(importedModuleNode);
639
640                        int referencesWithinCurrentModule = getReferenceCountWithinModuleOrGroup(moduleLevelIdentifiers,
641                                        currentModuleNode);
642
643                        if (referencesWithinCurrentModule == 0) {
644                                this.getLoggingInterface().logWarning(importedModuleIdentifier.getLine(),
645                                                importedModuleIdentifier.getEndLine(),
646                                                MessageClass.STYLE,
647                                                "No definitions from imported module \""
648                                                                + importedModuleIdentifier.getFirstChild().getText()
649                                                                + "\" are ever used!",
650                                                "6.18, " + MiscTools.getMethodName());
651                        }
652
653                } else if (importSpecNode.getType() == TTCN3ParserTokenTypes.ImportSpec) {
654                        LinkedList<LocationAST> importElementNodes = ASTUtil.findTypeNodes(importSpecNode,
655                                        TTCN3ParserTokenTypes.ImportElement);
656                        for (LocationAST importElementNode : importElementNodes) {
657
658                                if (isImportElementNonSpecific(importElementNode)) {
659                                        // generic
660                                        // any of type referenced?
661                                        ArrayList<LocationAST> moduleLevelIdentifiers = LocationAST.getModuleLevelIdentifiersOfType(importedModuleNode,
662                                                        getCorrespondingModuleDefinitionType(importElementNode));
663                                        int referencesWithinCurrentModule = 0;
664                                        if (importElementNode.getFirstChild().getType() != TTCN3ParserTokenTypes.ImportGroupSpec) {
665                                                referencesWithinCurrentModule = getReferenceCountWithinModuleOrGroup(moduleLevelIdentifiers,
666                                                                currentModuleNode);
667
668                                        } else {
669                                                // group handling
670                                                for (LocationAST importedGroupIdentifer : moduleLevelIdentifiers) {
671                                                        ArrayList<LocationAST> groupLevelIdentifiers = LocationAST.getModuleOrGroupLevelIdentifiers(LocationAST.resolveParentsUntilType(importedGroupIdentifer,
672                                                                        TTCN3ParserTokenTypes.GroupDef));
673                                                        referencesWithinCurrentModule += getReferenceCountWithinModuleOrGroup(groupLevelIdentifiers,
674                                                                        currentModuleNode);
675                                                }
676                                        }
677                                        if (referencesWithinCurrentModule == 0) {
678                                                this.getLoggingInterface().logWarning(importedModuleIdentifier.getLine(),
679                                                                importedModuleIdentifier.getEndLine(),
680                                                                MessageClass.STYLE,
681                                                                "No definitions of type \""
682                                                                                + LocationAST.getTTCN3ParserTokenTypeTypePrettyName(getCorrespondingModuleDefinitionType(importElementNode))
683                                                                                + "\" from imported module \""
684                                                                                + importedModuleIdentifier.getFirstChild().getText()
685                                                                                + "\" are ever used!",
686                                                                "6.18, " + MiscTools.getMethodName());
687                                        }
688
689                                } else {
690                                        // specific
691                                        LinkedList<LocationAST> identifierNodes = ASTUtil.findTypeNodes(importElementNode,
692                                                        TTCN3ParserTokenTypes.Identifier);
693                                        for (LocationAST identifierNode : identifierNodes) {
694                                                Symbol s = identifierNode.getFirstChild().getSymbol();
695                                                if (s == null) {
696                                                        // identifier not resolvable?
697                                                        this.getLoggingInterface().logInformation(identifierNode.getLine(),
698                                                                        identifierNode.getEndLine(),
699                                                                        MessageClass.STYLE,
700                                                                        "Definition for \""
701                                                                                        + identifierNode.getFirstChild().getText()
702                                                                                        + "\" of type \""
703                                                                                        + LocationAST.getTTCN3ParserTokenTypeTypePrettyName(getCorrespondingModuleDefinitionType(importElementNode))
704                                                                                        + "\" from imported module \""
705                                                                                        + importedModuleIdentifier.getFirstChild().getText()
706                                                                                        + "\" cannot be resolved!",
707                                                                        "6.18, " + MiscTools.getMethodName());
708                                                } else {
709                                                        if (!isNodeEqualToNode(ASTUtil.getModuleNode(importedModuleSymbol.getDeclarationNode()),
710                                                                        ASTUtil.getModuleNode(s.getDeclarationNode()))) {
711                                                                // identifier already imported?
712                                                                // (declarationNode.module != importedModule)
713                                                                // this should happen only if the declaration
714                                                                // actually exists in the imported module
715                                                                ArrayList<LocationAST> moduleLevelIdentifiers = LocationAST.getModuleLevelIdentifiersOfType(importedModuleNode,
716                                                                                getCorrespondingModuleDefinitionType(importElementNode));
717                                                                boolean importedModuleContainsIdentifierInQuestion = false;
718                                                                for (LocationAST moduleLevelIdentifier : moduleLevelIdentifiers) {
719                                                                        if (moduleLevelIdentifier.getFirstChild().getText().equals(identifierNode.getFirstChild().getText())) {
720                                                                                importedModuleContainsIdentifierInQuestion = true;
721                                                                        }
722                                                                }
723                                                                if (!importedModuleContainsIdentifierInQuestion) {
724                                                                        this.getLoggingInterface().logInformation(identifierNode.getLine(),
725                                                                                        identifierNode.getEndLine(),
726                                                                                        MessageClass.STYLE,
727                                                                                        "Imported definition for "
728                                                                                                        + identifierNode.getFirstChild().getText()
729                                                                                                        + " is not found in corresponding imported module \""
730                                                                                                        + ASTUtil.getEnclosingModuleName(importedModuleNode)
731                                                                                                        + "\", but it is already imported from module \""
732                                                                                                        + ASTUtil.getEnclosingModuleName(s.getDeclarationNode())
733                                                                                                        + "\"!",
734                                                                                        "6.18, "
735                                                                                                        + MiscTools.getMethodName());
736                                                                } else {
737                                                                        this.getLoggingInterface().logInformation(identifierNode.getLine(),
738                                                                                        identifierNode.getEndLine(),
739                                                                                        MessageClass.STYLE,
740                                                                                        "Imported definition for "
741                                                                                                        + identifierNode.getFirstChild().getText()
742                                                                                                        + " is ambiguous (already imported from module \""
743                                                                                                        + ASTUtil.getEnclosingModuleName(s.getDeclarationNode())
744                                                                                                        + "\")!",
745                                                                                        "6.18, "
746                                                                                                        + MiscTools.getMethodName());
747                                                                }
748                                                        } else {
749                                                                // identifier referenced?
750                                                                if (identifierNode.getParent().getType() != TTCN3ParserTokenTypes.FullGroupIdentifier) {
751                                                                        int referencesWithinCurrentModule = getReferenceCountWithinModule(identifierNode,
752                                                                                        currentModuleNode);
753                                                                        if (referencesWithinCurrentModule == 0) {
754                                                                                this.getLoggingInterface().logWarning(identifierNode.getLine(),
755                                                                                                identifierNode.getEndLine(),
756                                                                                                MessageClass.STYLE,
757                                                                                                "Imported definition for "
758                                                                                                                + identifierNode.getFirstChild().getText()
759                                                                                                                + " is never used!",
760                                                                                                "6.18, "
761                                                                                                                + MiscTools.getMethodName());
762                                                                        }
763                                                                } else {
764                                                                        // any reference of grouped elements
765                                                                        // check if it is a nested group import
766                                                                        if ((identifierNode.getNextSibling() == null)) {
767                                                                                LocationAST importedGroupDeclarationNode = s.getDeclarationNode();
768                                                                                // System.out.println();
769
770                                                                                ArrayList<LocationAST> identifiersWithinGroup = LocationAST.getModuleOrGroupLevelIdentifiers(LocationAST.resolveParentsUntilType(importedGroupDeclarationNode,
771                                                                                                TTCN3ParserTokenTypes.GroupDef));
772                                                                                // importedGroupDeclarationNode.getNthParent(2));
773                                                                                int referencesWithinCurrentModule = getReferenceCountWithinModuleOrGroup(identifiersWithinGroup,
774                                                                                                currentModuleNode);
775
776                                                                                if (referencesWithinCurrentModule == 0) {
777                                                                                        this.getLoggingInterface().logWarning(importedModuleIdentifier.getLine(),
778                                                                                                        importedModuleIdentifier.getEndLine(),
779                                                                                                        MessageClass.STYLE,
780                                                                                                        "No definitions from imported group \""
781                                                                                                                        + identifierNode.getFirstChild().getText()
782                                                                                                                        + "\" from module \""
783                                                                                                                        + importedModuleIdentifier.getFirstChild().getText()
784                                                                                                                        + "\" are ever used!",
785                                                                                                        "6.18, "
786                                                                                                                        + MiscTools.getMethodName());
787                                                                                }
788                                                                        }
789
790                                                                }
791                                                        }
792                                                }
793                                        }
794                                }
795                        }
796                }
797
798        }
799
800        // -------------------------------------------------------------------------------------------
801
802        public void checkNoOverSpecificRunsOnClauses(LocationAST node) {
803                //TODO: adapt to new paradigm
804                int componentElementReferencesWithinScope = 0;
805                LocationAST componentIdentifier = node.getNthChild(3);
806                Symbol componentSymbol = componentIdentifier.getSymbol();
807                if (componentSymbol == null) {
808                        this.getLoggingInterface().logInformation(componentIdentifier.getLine(),
809                                        componentIdentifier.getEndLine(),
810                                        MessageClass.STYLE,
811                                        "Definition for \""
812                                                        + componentIdentifier.getText()
813                                                        + "\" cannot be resolved, therefore it cannot be determined whether an over specific runs on clause is used in the definition of \""
814                                                        + node.getContainingModuleDefinitionIdentifiersList().get(0).getFirstChild().getText()
815                                                        + "\"!",
816                                        "6.13, " + MiscTools.getMethodName());
817                        return;
818                }
819                LocationAST componentDeclarationNode = componentSymbol.getDeclarationNode();
820                LocationAST componentModuleDefinitionNode = LocationAST.resolveParentsUntilType(componentDeclarationNode,
821                                TTCN3ParserTokenTypes.ModuleDefinition);
822                if (componentModuleDefinitionNode == null) {
823                        //TODO: need to output info? likely to happen at all?
824                        return;
825                }
826
827                ArrayList<Symbol> localDefinitionsSymbolsList = new ArrayList<Symbol>();
828                ArrayList<LocationAST> localDefinitionsIdentifiersList = LocationAST.getLocalDefinitionsIdentifiersList(componentModuleDefinitionNode);
829                if (localDefinitionsIdentifiersList==null) {
830                        this.getLoggingInterface()
831                                .logInformation(componentIdentifier.getLine(),
832                                                componentIdentifier.getEndLine(),
833                                                MessageClass.STYLE,
834                                                "Reference to \""
835                                                                + componentIdentifier.getText()
836                                                                + "\" in a runs on clause does not resolve to a component type definition! It could be an error!",
837                                                "6.13, " + MiscTools.getMethodName());
838                        return; //componentIdentifierNode does not correspond to a component definition
839                }
840                for (LocationAST localDefinitionIdentifier : localDefinitionsIdentifiersList) {
841                        Symbol s = localDefinitionIdentifier.getFirstChild().getSymbol();
842                        if (s == null) {
843                                this.getLoggingInterface().logFix(localDefinitionIdentifier.getLine(),
844                                                localDefinitionIdentifier.getLine(),
845                                                MessageClass.STYLE,
846                                                "Symbol resolution failed for "
847                                                                + localDefinitionIdentifier.getFirstChild().getText(),
848                                                "6.13, " + MiscTools.getMethodName());
849                        } else {
850                                localDefinitionsSymbolsList.add(s);
851                        }
852                }
853               
854               
855                LocationAST moduleDefinitionNode = LocationAST.resolveParentsUntilType(node,
856                                TTCN3ParserTokenTypes.ModuleDefinition);
857                LinkedHashSet<LocationAST> relevantModuleDefinitions = new LinkedHashSet<LocationAST>();
858                relevantModuleDefinitions.add(moduleDefinitionNode);
859
860                if (T3Q.activeProfile.isRecursionInCheckNoOverSpecificRunsOnClauses()) {
861                        LinkedHashSet<LocationAST> collectedReferences = collectReferencedFunctionsAndAltsteps(moduleDefinitionNode);
862                        relevantModuleDefinitions.addAll(collectedReferences);
863                }
864               
865                ReferenceFinder referenceFinder = new ReferenceFinder();
866
867                Map<String, List<ReferenceWithContext>> referenceMap = referenceFinder
868                                .findReferences(localDefinitionsSymbolsList);
869               
870                for (List<ReferenceWithContext> refWithContextList : referenceMap.values()){
871                        for (ReferenceWithContext refWithContext : refWithContextList){
872                                LocationAST referenceNode = refWithContext.getReferenceNode();
873                                for (LocationAST moduleDefinition : relevantModuleDefinitions) {
874                                        if (isReferenceWithinModuleDefinition(referenceNode,
875                                                        moduleDefinition)) {
876                                                componentElementReferencesWithinScope++;
877                                        }
878                                }
879                        }
880                }
881               
882                if (componentElementReferencesWithinScope == 0) {
883                        this.getLoggingInterface().logWarning(moduleDefinitionNode.getLine(),
884                                        moduleDefinitionNode.getLine(),
885                                        MessageClass.STYLE,
886                                        "Definition for \""
887                                                        + LocationAST.getModuleDefinitionIdentifiersList(moduleDefinitionNode).get(0).getFirstChild().getText()
888                                                        + "\" contains an over specific runs on clause!",
889                                        "6.13, " + MiscTools.getMethodName());
890                }
891        }
892
893
894        //TODO: consider splitting again
895        //TODO: does not include defaults?!
896        private LinkedHashSet<LocationAST> collectReferencedFunctionsAndAltsteps(
897                        LocationAST moduleDefinitionNode) {
898                LinkedHashSet<LocationAST> relevantModuleDefinitions = new LinkedHashSet<LocationAST>();
899                if (cyclicFunctionReferences.contains(moduleDefinitionNode)) {
900                        String cycle = "";
901                        for (LocationAST x : cyclicFunctionReferences){
902                                cycle+=LocationAST.getModuleDefinitionIdentifiersList(x).get(0).getFirstChild().getText()+", ";
903                        }
904                        cycle+=LocationAST.getModuleDefinitionIdentifiersList(moduleDefinitionNode).get(0).getFirstChild().getText();
905                        this
906                        .getLoggingInterface()
907                        .logInformation(
908                                        moduleDefinitionNode.getLine(),
909                                        moduleDefinitionNode.getEndLine(),
910                                        MessageClass.STYLE,
911                                        ""
912                                                        + "Possible cyclic call sequence: \""
913                                                        + cycle
914                                                        + "\". Skipping...",
915                                        "6.13, " + MiscTools.getMethodName());
916                } else {
917                        cyclicFunctionReferences.push(moduleDefinitionNode);
918                        LinkedList<LocationAST> referenceNodes = ASTUtil.findTypeNodes(
919                                        moduleDefinitionNode, TTCN3ParserTokenTypes.FunctionRef);
920                        referenceNodes.addAll(ASTUtil.findTypeNodes(moduleDefinitionNode,
921                                        TTCN3ParserTokenTypes.AltstepInstance));
922
923                        for (LocationAST referenceNode : referenceNodes) {
924                                LocationAST referenceIdentifier = referenceNode.getFirstChild()
925                                                .getFirstChild();
926                                Symbol referenceSymbol = referenceIdentifier.getSymbol();
927
928                                if (referenceSymbol != null) {
929                                        if (((referenceSymbol instanceof FunctionSymbol) && !((FunctionSymbol) referenceSymbol)
930                                                        .isExternal())
931                                                        || referenceSymbol instanceof AltstepSymbol) {
932                                                LocationAST declarationNode = referenceSymbol
933                                                                .getDeclarationNode();
934
935                                                if (declarationNode != null) {
936                                                        LocationAST referenceModuleDefinitionNode = LocationAST
937                                                                        .resolveParentsUntilType(
938                                                                                        declarationNode,
939                                                                                        TTCN3ParserTokenTypes.ModuleDefinition);
940                                                        relevantModuleDefinitions
941                                                                        .add(referenceModuleDefinitionNode);
942                                                        relevantModuleDefinitions
943                                                                        .addAll(collectReferencedFunctionsAndAltsteps(referenceModuleDefinitionNode));
944                                                }
945                                        }
946                                } else {
947                                        this
948                                                        .getLoggingInterface()
949                                                        .logInformation(
950                                                                        referenceIdentifier.getLine(),
951                                                                        referenceIdentifier.getEndLine(),
952                                                                        MessageClass.STYLE,
953                                                                        ""
954                                                                                        + "Definition for reference \""
955                                                                                        + referenceIdentifier.getText()
956                                                                                        + "\" cannot be resolved. It may not be possible to determine whether the enclosing construct has an over-specific runs on clause!",
957                                                                        "6.13, " + MiscTools.getMethodName());
958
959                                }
960                        }
961                        cyclicFunctionReferences.pop();
962                }
963                return relevantModuleDefinitions;
964        }
965
966        // -------------------------------------------------------------------------------------------
967
968        public void checkNoInlineTemplates(LocationAST node){
969                boolean problemOccured = false;
970                if (node.getFirstChild().getType() == TTCN3ParserTokenTypes.Type ||
971                                node.getFirstChild().getType() == TTCN3ParserTokenTypes.Signature ){
972                        problemOccured = true;
973                }
974                if (problemOccured) {
975                        this.getLoggingInterface().logWarning(node.getLine(),
976                                        node.getEndLine(),
977                                        MessageClass.STYLE,
978                                        "Inline Template is used!",
979                                        "6.13, " + MiscTools.getMethodName());
980                       
981                }
982        }
983       
984        // -------------------------------------------------------------------------------------------
985        //TODO: consider group definitions as well? currently: yes
986        //implementation of 6.17
987        //the additional parts in 6.11 will be implemented separately as "checkZeroReferencedLocalDefinitions"
988        public void checkZeroReferencedModuleDefinitions(LocationAST node) {
989
990                Pattern zeroReferencedModuleDefinitionsExcludedPattern = Pattern.compile(T3Q.activeProfile.getZeroReferencedModuleDefinitionsExcludedRegExp());
991                Matcher zeroReferencedModuleDefinitionsExcludedMatcher = zeroReferencedModuleDefinitionsExcludedPattern.matcher(ASTUtil.getEnclosingModuleName(node));
992                ;
993
994                if (zeroReferencedModuleDefinitionsExcludedMatcher.matches()) {
995                        return;
996                }
997                //exclude groups
998                if (LocationAST.getModuleDefinitionTypeNode(node).getType()==TTCN3ParserTokenTypes.GroupDef) {
999                        return;
1000                }
1001               
1002                ArrayList<LocationAST> identifiersList = LocationAST.getModuleDefinitionIdentifiersList(node);
1003                LocationAST identifierNode = null;
1004                String identifierText = null;
1005                for (int i = 0; i < identifiersList.size(); i++) {
1006                        identifierNode = identifiersList.get(i);
1007                        identifierText = identifierNode.getFirstChild().getText();
1008                        Symbol s = identifierNode.getFirstChild().getSymbol();
1009
1010                        if (s == null) {
1011                                this.getLoggingInterface().logFix(identifierNode.getLine(),
1012                                                identifierNode.getLine(),
1013                                                MessageClass.STYLE,
1014                                                "Symbol resolution failed for " + identifierText
1015                                                                + " in " + MiscTools.getMethodName(),
1016                                                "6.17, " + MiscTools.getMethodName());
1017                                return;
1018                        }
1019                        ReferenceFinder referenceFinder = new ReferenceFinder();
1020                        if (referenceFinder.countReferences(s) == 0) {
1021                                // TODO: add stats counters
1022                                // TODO: add type information
1023                                // TODO: groups shall probably be excluded
1024                                this.getLoggingInterface().logWarning(identifierNode.getLine(),
1025                                                identifierNode.getEndLine(),
1026                                                MessageClass.STYLE,
1027                                                "Definition for \"" + identifierText
1028                                                                + "\" is never referenced!",
1029                                                "6.17, " + MiscTools.getMethodName());
1030                        } else {
1031                                int referencesOutsideImports = 0;
1032                                Map<String, List<ReferenceWithContext>> referenceMap = referenceFinder.findReferences(s);
1033                                Iterator<List<ReferenceWithContext>> referenceMapIterator = referenceMap.values().iterator();
1034                                while (referenceMapIterator.hasNext()) {
1035                                        Iterator<ReferenceWithContext> referenceIterator = referenceMapIterator.next().iterator();
1036                                        while (referenceIterator.hasNext()) {
1037                                                LocationAST referenceNode = referenceIterator.next().getReferenceNode();
1038                                                // System.out.println("++++> "+referenceNode);
1039                                                if (!isReferenceWithinImport(referenceNode)) {
1040                                                        referencesOutsideImports++;
1041                                                }
1042                                        }
1043                                }
1044                                if (referencesOutsideImports == 0) {
1045                                        this.getLoggingInterface().logWarning(identifierNode.getLine(),
1046                                                        identifierNode.getEndLine(),
1047                                                        MessageClass.STYLE,
1048                                                        "Definition for \""
1049                                                                        + identifierText
1050                                                                        + "\" is only referenced within import statements!",
1051                                                        "6.17, " + MiscTools.getMethodName());
1052
1053                                }
1054                        }
1055                }
1056
1057        }
1058
1059        // -------------------------------------------------------------------------------------------
1060       
1061        //TODO:
1062        //Arguably, this should be migrated to the symbol table and support multiple declarations for the same entity and then resolve them based on type, but this is a long term future consideration
1063        //Alternatively, this shall be split and most of it shall be migrated to the visitor to accommodate reuse for 1.6.3
1064        public void checkNoDuplicatedModuleDefinitionIdentifiers(LocationAST node) {
1065                ArrayList<LocationAST> identifiersList = LocationAST.getModuleDefinitionIdentifiersList(node);
1066                LocationAST identifierNode = null;
1067                String identifierText = null;
1068                for (int i = 0; i < identifiersList.size(); i++){
1069                        totalIdentifierCount++; //TODO: replace with statistics interface
1070                        identifierNode = identifiersList.get(i);
1071                        identifierText = identifierNode.getFirstChild().getText();
1072                        if (moduleLevelIdentifiersMap.containsKey(identifierText)){
1073                                repeatedIdentifierCount++; //TODO: replace with statistics interface
1074                                ArrayList<LocationAST> locationNodes = moduleLevelIdentifiersMap.get(identifierText);
1075                                String locationsList = "";
1076                                String moduleName = "";
1077                                for (int l = 0; l < locationNodes.size(); l++){
1078                                        moduleName = ASTUtil.getModuleSymbol(locationNodes.get(l)).getName();
1079                                        locationsList+= "<\""+moduleName+"\": "+locationNodes.get(l).getLine()+">, ";
1080                                }
1081                                locationsList = locationsList.substring(0, locationsList.length()-2);
1082                       
1083                                this.getLoggingInterface().logWarning(identifiersList.get(i).getLine(),
1084                                                identifiersList.get(i).getEndLine(),
1085                                                MessageClass.STYLE,
1086                                                "Identifier \""
1087                                                                + identifierText
1088                                                                + "\" on the module level has already been used in "
1089                                                                + locationsList + "!",
1090                                                "6.10, " + MiscTools.getMethodName());
1091                        }
1092                        addModuleLevelIdentifier(identifierNode);
1093
1094                }
1095
1096        }
1097       
1098        // -------------------------------------------------------------------------------------------
1099
1100        public void checkModuleSize(LocationAST node) {
1101                int moduleSize = node.getEndOffset() - node.getOffset();
1102                int referenceSize = T3Q.activeProfile.getMaximumAllowedModuleSizeInBytes();
1103                if (moduleSize > referenceSize) {
1104                        String moduleIdentifier = ASTUtil.findChild(node,
1105                                        TTCN3ParserTokenTypes.Identifier).getFirstChild().getText();
1106
1107                        this.getLoggingInterface().logWarning(node.getLine(),
1108                                        node.getEndLine(),
1109                                        MessageClass.MODULARIZATION,
1110                                        "Module \"" + moduleIdentifier + "\" is bigger ("
1111                                                        + moduleSize
1112                                                        + " bytes) that the maximum allowed module size ("
1113                                                        + referenceSize + " bytes)!",
1114                                        "7.21, " + MiscTools.getMethodName());
1115
1116                }
1117        }
1118
1119        // -------------------------------------------------------------------------------------------
1120
1121        public void checkModuleContainment(LocationAST node,
1122                        String moduleRestriction) {
1123                if (node.getType() == TTCN3ParserTokenTypes.TTCN3ModuleId) {
1124                        LocationAST textNode = node.getNthChild(4);
1125                        String moduleName = textNode.getText();
1126                        if (!moduleName.contains(moduleRestriction)) {
1127                                return;
1128                        }
1129
1130                }
1131
1132                LocationAST moduleDefinitionsList = null;
1133
1134                if (node.getType() == TTCN3ParserTokenTypes.GroupDef) {
1135                        if (node.getFirstChild().getNextSibling() == null) {
1136                                return;
1137                        }
1138                        moduleDefinitionsList = node.getFirstChild().getNextSibling().getFirstChild();
1139                } else {
1140                        if ((node.getNextSibling() == null)
1141                                        || (node.getNextSibling().getType() != TTCN3ParserTokenTypes.ModuleDefinitionsPart)) {
1142                                return;
1143                        }
1144                        moduleDefinitionsList = node.getNextSibling().getFirstChild();
1145                }
1146
1147                LocationAST moduleDefinition = moduleDefinitionsList.getFirstChild();
1148                do {
1149                        if (moduleDefinition.getType() == TTCN3ParserTokenTypes.ModuleDefinition) {
1150                                LocationAST definitionTypeNode = moduleDefinition.getFirstChild();
1151                                if (definitionTypeNode.getType() == TTCN3ParserTokenTypes.Visibility){
1152                                        definitionTypeNode = definitionTypeNode.getNextSibling();
1153                                }
1154
1155                                if (definitionTypeNode.getType() == TTCN3ParserTokenTypes.GroupDef) {
1156                                        checkModuleContainment(definitionTypeNode,
1157                                                        moduleRestriction);
1158                                } else {
1159                                        if (!moduleRestriction.equals("TypesAndValues")
1160                                                        && (definitionTypeNode.getType() == TTCN3ParserTokenTypes.TypeDef)
1161                                                        && (definitionTypeNode.getFirstChild().getType() == TTCN3ParserTokenTypes.StructuredTypeDef)) {
1162                                                // if definition is of the non-specific type TypeDef,
1163                                                // with sub-type StructuredDefType, descend two levels
1164                                                // in the tree to get the relevant nodes that are
1165                                                // specific enough for restrictions other than
1166                                                // TypesAndValues
1167                                                definitionTypeNode = definitionTypeNode.getFirstChild().getFirstChild();
1168
1169                                        }
1170                                        if (!moduleContentsChecker.typePermittedInRestrictedModule(moduleRestriction,
1171                                                        definitionTypeNode.getType())) {
1172
1173                                                this.getLoggingInterface().logWarning(definitionTypeNode.getLine(),
1174                                                                definitionTypeNode.getEndLine(),
1175                                                                MessageClass.MODULARIZATION,
1176                                                                "Definition in "
1177                                                                                + moduleRestriction
1178                                                                                + " module is not of the permissible definition type(s)!",
1179                                                                "7.x, " + MiscTools.getMethodName());
1180                                        } else {
1181                                                // special case scenario
1182                                                if ((moduleRestriction.equals("Testcases"))
1183                                                                && (definitionTypeNode.getType() == TTCN3ParserTokenTypes.FunctionDef)) {
1184
1185                                                        if (!isFunctionStartsBehavior(definitionTypeNode.getFirstChild().getFirstChild())) {
1186                                                                this.getLoggingInterface().logWarning(definitionTypeNode.getLine(),
1187                                                                                definitionTypeNode.getEndLine(),
1188                                                                                MessageClass.MODULARIZATION,
1189                                                                                "Definition in "
1190                                                                                                + moduleRestriction
1191                                                                                                + " module is not of the permissible definition type(s)! Function is never referenced in a start statement!",
1192                                                                                "7.x, " + MiscTools.getMethodName());
1193                                                        }
1194
1195                                                }
1196                                        }
1197                                }
1198                        }
1199                } while ((moduleDefinition = moduleDefinition.getNextSibling()) != null);
1200        }
1201
1202        // -------------------------------------------------------------------------------------------
1203
1204        public void checkPortMessageGrouping(LocationAST node) {
1205
1206                String portModuleName = ASTUtil.getEnclosingModuleName(node);
1207                String portIdentifierText = ASTUtil.findChild(node, TTCN3ParserTokenTypes.IDENTIFIER).getText();
1208
1209                LocationAST portGroupDef = LocationAST.resolveParentsUntilType(node,
1210                                TTCN3ParserTokenTypes.GroupDef);
1211
1212                if (portGroupDef == null) {
1213
1214                        this.getLoggingInterface().logWarning(node.getLine(),
1215                                        node.getEndLine(),
1216                                        MessageClass.STRUCTURE,
1217                                        "Port type definition for \""
1218                                        + portIdentifierText
1219                                        + "\" is found outside a group definition! Related messages can therefore never be in the same group as the port definition!",
1220                                        "4.2, " + MiscTools.getMethodName());
1221
1222                } else {
1223                        LocationAST portDefAttribsNode = node.getFirstChild().getNextSibling();
1224
1225                        LocationAST portDefAttribsList = portDefAttribsNode.getFirstChild();
1226                        do {
1227                                LinkedList<LocationAST> identifierList = ASTUtil.findTypeNodes(portDefAttribsList,
1228                                                TTCN3ParserTokenTypes.Identifier);
1229                                for (int j = 0; j < identifierList.size(); j++) {
1230                                        LocationAST identifierNode = identifierList.get(j);
1231
1232                                        Symbol symbol = null;
1233                                        String type = null;
1234                                        if (identifierNode.getParent().getType() == TTCN3ParserTokenTypes.Signature) {
1235                                                type = "Signature";
1236
1237                                        } else {
1238                                                if (identifierNode.getParent().getType() == TTCN3ParserTokenTypes.TypeReference) {
1239                                                        type = "Message type";
1240                                                }
1241                                        }
1242                                        if (type != null) {
1243                                                symbol = identifierNode.getFirstChild().getSymbol();
1244
1245                                                if (symbol == null) {
1246
1247                                                        this.getLoggingInterface().logWarning(identifierNode.getLine(),
1248                                                                        identifierNode.getEndLine(),
1249                                                                        MessageClass.STRUCTURE,
1250                                                                        ""
1251                                                                        + type
1252                                                                        + " definition for \""
1253                                                                        + identifierNode.getFirstChild().getText()
1254                                                                        + "\" related to port type definition for \""
1255                                                                        + portIdentifierText
1256                                                                        + "\" cannot be resolved! It is therefore not in the same group!",
1257                                                                        "4.2, " + MiscTools.getMethodName());
1258
1259                                                       
1260                                                } else {
1261                                                        LocationAST declarationIdentifierNode = symbol.getDeclarationNode();
1262
1263                                                        String declarationModuleName = ASTUtil.getEnclosingModuleName(declarationIdentifierNode);
1264
1265                                                        LocationAST declarationGroupDef = LocationAST.resolveParentsUntilType(declarationIdentifierNode,
1266                                                                        TTCN3ParserTokenTypes.GroupDef);
1267                                                        if (declarationGroupDef == null) {
1268                                                                this.getLoggingInterface().logWarning(identifierNode.getLine(),
1269                                                                                identifierNode.getEndLine(),
1270                                                                                MessageClass.STRUCTURE,
1271                                                                                ""
1272                                                                                                + type
1273                                                                                                + " definition for \""
1274                                                                                                + declarationIdentifierNode.getText()
1275                                                                                                + "\" <"
1276                                                                                                + declarationIdentifierNode.getLine()
1277                                                                                                + ","
1278                                                                                                + declarationModuleName
1279                                                                                                + ",- "
1280                                                                                                + "> "
1281                                                                                                + "related to port type definition for \""
1282                                                                                                + portIdentifierText
1283                                                                                                + "\" <"
1284                                                                                                + node.getLine()
1285                                                                                                + ","
1286                                                                                                + portModuleName
1287                                                                                                + ","
1288                                                                                                + portGroupDef.getNthChild(2).getText()
1289                                                                                                + "> "
1290                                                                                                + "is found outside a group definition! It can therefore never be in the same group as the port type definition!",
1291                                                                                "4.2, " + MiscTools.getMethodName());
1292
1293                                                        } else {
1294                                                                if (declarationModuleName.equals(portModuleName)) {
1295                                                                        if (!portGroupDef.equals(declarationGroupDef)) {
1296                                                                                if (!isNodeWithinGroup(declarationGroupDef,
1297                                                                                                portGroupDef)) {
1298
1299                                                                                        this.getLoggingInterface().logWarning(identifierNode.getLine(),
1300                                                                                                        identifierNode.getEndLine(),
1301                                                                                                        MessageClass.STRUCTURE,
1302                                                                                                        ""
1303                                                                                                                        + type
1304                                                                                                                        + " definition for \""
1305                                                                                                                        + declarationIdentifierNode.getText()
1306                                                                                                                        + "\" <"
1307                                                                                                                        + declarationIdentifierNode.getLine()
1308                                                                                                                        + ","
1309                                                                                                                        + declarationModuleName
1310                                                                                                                        + ","
1311                                                                                                                        + declarationGroupDef.getNthChild(2).getText()
1312                                                                                                                        + "> "
1313                                                                                                                        + "related to port type definition for \""
1314                                                                                                                        + portIdentifierText
1315                                                                                                                        + "\" <"
1316                                                                                                                        + node.getLine()
1317                                                                                                                        + ","
1318                                                                                                                        + portModuleName
1319                                                                                                                        + ","
1320                                                                                                                        + portGroupDef.getNthChild(2).getText()
1321                                                                                                                        + "> "
1322                                                                                                                        + "is not within the same group as the port type definition!",
1323                                                                                                        "4.2, "
1324                                                                                                                        + MiscTools.getMethodName());
1325                                                                                       
1326                                                                                } else {
1327                                                                                        this.getLoggingInterface().logInformation(identifierNode.getLine(),
1328                                                                                                        identifierNode.getEndLine(),
1329                                                                                                        MessageClass.STRUCTURE,
1330                                                                                                        ""
1331                                                                                                                        + type
1332                                                                                                                        + " definition for \""
1333                                                                                                                        + declarationIdentifierNode.getText()
1334                                                                                                                        + "\" <"
1335                                                                                                                        + declarationIdentifierNode.getLine()
1336                                                                                                                        + ","
1337                                                                                                                        + declarationModuleName
1338                                                                                                                        + ","
1339                                                                                                                        + declarationGroupDef.getNthChild(2).getText()
1340                                                                                                                        + "> "
1341                                                                                                                        + "related to port type definition for \""
1342                                                                                                                        + portIdentifierText
1343                                                                                                                        + "\" <"
1344                                                                                                                        + node.getLine()
1345                                                                                                                        + ","
1346                                                                                                                        + portModuleName
1347                                                                                                                        + ","
1348                                                                                                                        + portGroupDef.getNthChild(2).getText()
1349                                                                                                                        + "> "
1350                                                                                                                        + "is within a nested subgroup within the same group as the port type definition!",
1351                                                                                                        "4.2, "
1352                                                                                                                        + MiscTools.getMethodName());
1353                                                                                }
1354                                                                        }
1355                                                                } else {
1356                                                                        this.getLoggingInterface().logWarning(identifierNode.getLine(),
1357                                                                                        identifierNode.getEndLine(),
1358                                                                                        MessageClass.STRUCTURE,
1359                                                                                        ""
1360                                                                                                        + type
1361                                                                                                        + " definition for \""
1362                                                                                                        + declarationIdentifierNode.getText()
1363                                                                                                        + "\" <"
1364                                                                                                        + declarationIdentifierNode.getLine()
1365                                                                                                        + ","
1366                                                                                                        + declarationModuleName
1367                                                                                                        + ","
1368                                                                                                        + declarationGroupDef.getNthChild(2).getText()
1369                                                                                                        + "> "
1370                                                                                                        + "related to port type definition for \""
1371                                                                                                        + portIdentifierText
1372                                                                                                        + "\" <"
1373                                                                                                        + node.getLine()
1374                                                                                                        + ","
1375                                                                                                        + portModuleName
1376                                                                                                        + ","
1377                                                                                                        + portGroupDef.getNthChild(2).getText()
1378                                                                                                        + "> "
1379                                                                                                        + "is not within the same module as the port type definition! It can therefore never be in the same group as the port definition!",
1380
1381                                                                                        "4.2, " + MiscTools.getMethodName());
1382                                                                }
1383                                                        }
1384
1385                                                }
1386                                        }
1387
1388                                }
1389
1390                        } while ((portDefAttribsList = portDefAttribsList.getNextSibling()) != null);
1391
1392                }
1393
1394        }
1395
1396        // -------------------------------------------------------------------------------------------
1397
1398        public void checkTypeDefOrderInGroup(LocationAST node) {
1399                String previousDefinitionIdentifierText = null;
1400                String currentDefinitionIdentifierText = null;
1401                LocationAST groupIdentifierNode = node.getFirstChild();
1402                String groupIdentifierText = groupIdentifierNode.getFirstChild().getText();
1403
1404                if (groupIdentifierNode.getNextSibling() != null) {
1405                        LocationAST moduleDefinitionNode = groupIdentifierNode.getNextSibling()
1406                                        .getNthChild(2);
1407                        do {
1408                                if (moduleDefinitionNode.getType() != TTCN3ParserTokenTypes.SemiColon) {
1409                                        if (LocationAST.getModuleDefinitionTypeNode(moduleDefinitionNode).getType() == TTCN3ParserTokenTypes.TypeDef) {
1410                                                ArrayList<LocationAST> moduleDefinitionIdentifiersList = LocationAST.getModuleDefinitionIdentifiersList(moduleDefinitionNode);
1411                                                for (LocationAST moduleDefinitionIdentifier : moduleDefinitionIdentifiersList) {
1412                                                        currentDefinitionIdentifierText = moduleDefinitionIdentifier
1413                                                                        .getFirstChild().getText();
1414                                                        // switched to case insensitive ordering
1415                                                        if (previousDefinitionIdentifierText != null) {
1416                                                                if (currentDefinitionIdentifierText
1417                                                                                .compareToIgnoreCase(previousDefinitionIdentifierText) <= 0) {
1418                                                                        this.getLoggingInterface()
1419                                                                                        .logWarning(
1420                                                                                                        node.getLine(),
1421                                                                                                        node.getEndLine(),
1422                                                                                                        MessageClass.STRUCTURE,
1423                                                                                                        "Type definitions <\""
1424                                                                                                                        + previousDefinitionIdentifierText
1425                                                                                                                        + "\",\""
1426                                                                                                                        + currentDefinitionIdentifierText
1427                                                                                                                        + "\"> within group \""
1428                                                                                                                        + groupIdentifierText
1429                                                                                                                        + "\" are not alphabetically ordered!"
1430                                                                                                                        + "4.1, "
1431                                                                                                                        + MiscTools
1432                                                                                                                                        .getMethodName());
1433                                                                }
1434                                                        }
1435                                                        previousDefinitionIdentifierText = currentDefinitionIdentifierText;
1436                                                }
1437                                        }
1438                                }
1439                        } while ((moduleDefinitionNode = moduleDefinitionNode.getNextSibling()) != null);
1440                }
1441        }
1442
1443        // -------------------------------------------------------------------------------------------
1444
1445        public void checkLocalDefinitionsComeFirst(LocationAST node) {
1446                boolean hasOtherDefinitions = false;
1447                int previousLocalDefinitionsOrderLevel = 0;
1448                //TODO: REFACTOR!!! and reorganize
1449                ArrayList<Integer> configuredLocalDefinitionTypes = getConfiguredLocalDefinitionTypes();
1450                if (configuredLocalDefinitionTypes.size() == 0){
1451                        return;
1452                }
1453
1454                String definedLocalDefinitionOrder = "";
1455                for (String localDef : T3Q.activeProfile.getLocalDefinitionTypes()){
1456                        definedLocalDefinitionOrder += localDef+", ";
1457                }
1458                definedLocalDefinitionOrder = definedLocalDefinitionOrder.substring(0, definedLocalDefinitionOrder.length()-2);
1459               
1460                if (node.getFirstChild().getType() == TTCN3ParserTokenTypes.AltstepDef) {
1461                        LocationAST altstepLocalDefList = (LocationAST) ASTUtil
1462                                        .findSibling(node.getNthChild(2),
1463                                                        TTCN3ParserTokenTypes.AltstepLocalDefList);
1464
1465                        if (altstepLocalDefList != null) {
1466
1467                                LocationAST altstepLocalDef = altstepLocalDefList
1468                                                .getFirstChild();
1469
1470                                do {
1471                                        if (altstepLocalDef.getFirstChild() != null) {
1472                                                LocationAST definition = altstepLocalDef
1473                                                                .getFirstChild();
1474                                                if (configuredLocalDefinitionTypes.contains(definition.getType())) {
1475                                                        int currentLocalDefinitionTypeOrderLevel = configuredLocalDefinitionTypes.indexOf(definition.getType());
1476                                                        if (hasOtherDefinitions){
1477                                                                this.getLoggingInterface().logWarning(
1478                                                                                definition.getLine(),
1479                                                                                definition.getEndLine(),
1480                                                                                MessageClass.STYLE,
1481                                                                                "Local definition is not at the begining!",
1482                                                                                "6.8, " + MiscTools.getMethodName());
1483                                                               
1484                                                        } else {
1485                                                                if ((currentLocalDefinitionTypeOrderLevel < previousLocalDefinitionsOrderLevel)) {
1486                                                                        this.getLoggingInterface().logWarning(
1487                                                                                        definition.getLine(),
1488                                                                                        definition.getEndLine(),
1489                                                                                        MessageClass.STYLE,
1490                                                                                        "Local definition order is not maintained as configured ("
1491                                                                                        + definedLocalDefinitionOrder
1492                                                                                        + ")!" +
1493                                                                                        "6.8, " + MiscTools.getMethodName());
1494                                                                } else {
1495                                                                        previousLocalDefinitionsOrderLevel = currentLocalDefinitionTypeOrderLevel;
1496                                                                }
1497                                                        }
1498                                                } else {
1499                                                        hasOtherDefinitions = true;
1500                                                }
1501                                        }
1502                                } while ((altstepLocalDef = altstepLocalDef.getNextSibling()) != null);
1503
1504                        }
1505
1506                        LocationAST altstepGuardList = (LocationAST) ASTUtil.findSibling(
1507                                        node.getNthChild(2), TTCN3ParserTokenTypes.AltGuardList);
1508
1509                        if (altstepGuardList != null) {
1510
1511                                LinkedList<LocationAST> localDefNodes = new LinkedList<LocationAST>();
1512                                for (int configuredLocalDefinitionType : configuredLocalDefinitionTypes){
1513                                        localDefNodes.addAll(ASTUtil
1514                                                .findTypeNodes(altstepGuardList,
1515                                                                configuredLocalDefinitionType));
1516                                }
1517                                if (!localDefNodes.isEmpty()) {
1518                                        LocationAST localDefNode;
1519                                        for (int i = 0; i < localDefNodes.size(); i++) {
1520                                                localDefNode = localDefNodes.get(i);
1521                                                this.getLoggingInterface().logWarning(
1522                                                                localDefNode.getLine(),
1523                                                                localDefNode.getEndLine(),
1524                                                                MessageClass.STYLE,
1525                                                                "Local definition is not at the begining!",
1526                                                                "6.8, " + MiscTools.getMethodName());
1527                                        }
1528
1529                                }
1530                        }
1531
1532                }
1533                else if (node.getFirstChild().getType() == TTCN3ParserTokenTypes.FunctionDef
1534                                || node.getFirstChild().getType() == TTCN3ParserTokenTypes.TestcaseDef) {
1535                        LocationAST functionStatementBlock = (LocationAST) ASTUtil
1536                                        .findSibling(node.getNthChild(2),
1537                                                        TTCN3ParserTokenTypes.StatementBlock); // node.getFirstChild()
1538
1539                        if (functionStatementBlock != null) {
1540
1541                                LocationAST functionStatementOrDefNode = functionStatementBlock
1542                                                .getFirstChild();
1543
1544                                if (functionStatementOrDefNode == null) {
1545                                        return;
1546                                }
1547
1548                                do {
1549                                        if (functionStatementOrDefNode.getFirstChild() != null) {
1550                                                if ((functionStatementOrDefNode
1551                                                                .getType() == TTCN3ParserTokenTypes.FunctionLocalInst) ||
1552                                                                (functionStatementOrDefNode
1553                                                                .getType() == TTCN3ParserTokenTypes.FunctionLocalDef)) {
1554                                                        //duplicated
1555                                                        LocationAST definition = functionStatementOrDefNode
1556                                                                        .getFirstChild();
1557                                                        if (configuredLocalDefinitionTypes.contains(definition.getType())) {
1558                                                                int currentLocalDefinitionTypeOrderLevel = configuredLocalDefinitionTypes.indexOf(definition.getType());
1559                                                                if (hasOtherDefinitions) {
1560                                                                        this.getLoggingInterface().logWarning(
1561                                                                                        definition.getLine(),
1562                                                                                        definition.getEndLine(),
1563                                                                                        MessageClass.STYLE,
1564                                                                                        "Local definition is not at the begining!",
1565                                                                                        "6.8, " + MiscTools.getMethodName());
1566
1567                                                                } else {
1568                                                                        if ((currentLocalDefinitionTypeOrderLevel < previousLocalDefinitionsOrderLevel)) {
1569                                                                                this.getLoggingInterface().logWarning(
1570                                                                                                definition.getLine(),
1571                                                                                                definition.getEndLine(),
1572                                                                                                MessageClass.STYLE,
1573                                                                                                "Local definition order is not maintained as configured ("
1574                                                                                                + definedLocalDefinitionOrder
1575                                                                                                + ")!" +
1576                                                                                                "6.8, " + MiscTools.getMethodName());
1577                                                                        } else {
1578                                                                                previousLocalDefinitionsOrderLevel = currentLocalDefinitionTypeOrderLevel;
1579                                                                        }
1580
1581                                                                }
1582                                                        } else {
1583                                                                // it could be a timer
1584                                                                hasOtherDefinitions = true;
1585                                                        }
1586                                                } else {
1587                                                        // anything else
1588                                                        hasOtherDefinitions = true;
1589                                                        // search for local definition nodes
1590                                                        //duplicated
1591                                                        LinkedList<LocationAST> localDefNodes = new LinkedList<LocationAST>();
1592                                                        for (int configuredLocalDefinitionType : configuredLocalDefinitionTypes){
1593                                                                localDefNodes.addAll(ASTUtil
1594                                                                        .findTypeNodes(functionStatementOrDefNode,
1595                                                                                        configuredLocalDefinitionType));
1596                                                        }
1597
1598                                                       
1599                                                        if (!localDefNodes.isEmpty()) {
1600                                                                LocationAST localDefNode;
1601                                                                for (int i = 0; i < localDefNodes.size(); i++) {
1602                                                                        localDefNode = localDefNodes.get(i);
1603                                                                        this.getLoggingInterface().logWarning(
1604                                                                                        localDefNode.getLine(),
1605                                                                                        localDefNode.getEndLine(),
1606                                                                                        MessageClass.STYLE,
1607                                                                                        "Local definition is not at the begining!",
1608                                                                                        "6.8, " + MiscTools.getMethodName());
1609                                                                }
1610
1611                                                        }
1612
1613                                                }
1614                                        }
1615                                } while ((functionStatementOrDefNode = functionStatementOrDefNode
1616                                                .getNextSibling()) != null);
1617                        }
1618                }
1619
1620                else if ((node.getFirstChild().getType() == TTCN3ParserTokenTypes.TypeDef) && (node.getNthChild(3).getType() == TTCN3ParserTokenTypes.ComponentDef)) {
1621                        LinkedList<LocationAST> componentElementDefs = ASTUtil
1622                                        .findTypeNodes(node,
1623                                                        TTCN3ParserTokenTypes.ComponentElementDef);
1624                        for (LocationAST componentElementDef : componentElementDefs) {
1625                                // cloned
1626                                LocationAST definition = componentElementDef.getFirstChild();
1627                                if (configuredLocalDefinitionTypes.contains(definition
1628                                                .getType())) {
1629                                        int currentLocalDefinitionTypeOrderLevel = configuredLocalDefinitionTypes
1630                                                        .indexOf(definition.getType());
1631                                        if (hasOtherDefinitions) {
1632                                                this.getLoggingInterface().logWarning(
1633                                                                definition.getLine(),
1634                                                                definition.getEndLine(),
1635                                                                MessageClass.STYLE,
1636                                                                "Local definition is not at the begining!",
1637                                                                "6.8, " + MiscTools.getMethodName());
1638                                        } else {
1639                                                if ((currentLocalDefinitionTypeOrderLevel < previousLocalDefinitionsOrderLevel)) {
1640                                                        this.getLoggingInterface().logWarning(
1641                                                                        definition.getLine(),
1642                                                                        definition.getEndLine(),
1643                                                                        MessageClass.STYLE,
1644                                                                        "Local definition order is not maintained as configured ("
1645                                                                        + definedLocalDefinitionOrder
1646                                                                        + ")!" +
1647                                                                        "6.8, " + MiscTools.getMethodName());
1648
1649                                                } else {
1650                                                        previousLocalDefinitionsOrderLevel = currentLocalDefinitionTypeOrderLevel;
1651                                                }
1652
1653                                        }
1654                                } else {
1655                                        // it could be a timer
1656                                        hasOtherDefinitions = true;
1657                                }
1658
1659                        }
1660                }
1661               
1662        }
1663
1664        // -------------------------------------------------------------------------------------------
1665
1666        //TODO: largely duplicated, factor out
1667        public void checkLocalDefinitionsComeFirstWithinControlPart(LocationAST node) {
1668                boolean hasOtherDefinitions = false;
1669                int previousLocalDefinitionsOrderLevel = 0;
1670                // TODO: refactor and reorganize
1671                ArrayList<Integer> configuredLocalDefinitionTypes = getConfiguredLocalDefinitionTypes();
1672                if (configuredLocalDefinitionTypes.size() == 0) {
1673                        return;
1674                }
1675
1676                String definedLocalDefinitionOrder = "";
1677                for (String localDef : T3Q.activeProfile
1678                                .getLocalDefinitionTypes()) {
1679                        definedLocalDefinitionOrder += localDef + ", ";
1680                }
1681                definedLocalDefinitionOrder = definedLocalDefinitionOrder.substring(0,
1682                                definedLocalDefinitionOrder.length() - 2);
1683               
1684                LocationAST controlStatementOrDefNode = node
1685                .getFirstChild();
1686               
1687                if (controlStatementOrDefNode == null) {
1688                        return;
1689                }
1690
1691                do {
1692                        if (controlStatementOrDefNode.getFirstChild() != null) {
1693                                if ((controlStatementOrDefNode.getFirstChild()
1694                                                .getType() == TTCN3ParserTokenTypes.FunctionLocalInst) ||
1695                                                (controlStatementOrDefNode.getFirstChild()
1696                                                .getType() == TTCN3ParserTokenTypes.FunctionLocalDef)) {
1697                                        //duplicated
1698                                        LocationAST definition = controlStatementOrDefNode
1699                                                        .getFirstChild().getFirstChild();
1700                                        if (configuredLocalDefinitionTypes.contains(definition.getType())) {
1701                                                int currentLocalDefinitionTypeOrderLevel = configuredLocalDefinitionTypes.indexOf(definition.getType());
1702                                                if (hasOtherDefinitions) {
1703                                                        this.getLoggingInterface().logWarning(
1704                                                                        definition.getLine(),
1705                                                                        definition.getEndLine(),
1706                                                                        MessageClass.STYLE,
1707                                                                        "Local definition is not at the begining!",
1708                                                                        "6.8, " + MiscTools.getMethodName());
1709                                                } else {
1710                                                        if ((currentLocalDefinitionTypeOrderLevel < previousLocalDefinitionsOrderLevel)) {
1711                                                                this.getLoggingInterface().logWarning(
1712                                                                                definition.getLine(),
1713                                                                                definition.getEndLine(),
1714                                                                                MessageClass.STYLE,
1715                                                                                "Local definition order is not maintained as configured ("+definedLocalDefinitionOrder+")!",
1716                                                                                "6.8, " + MiscTools.getMethodName());
1717                                                        } else {
1718                                                                previousLocalDefinitionsOrderLevel = currentLocalDefinitionTypeOrderLevel;
1719                                                        }
1720                                                }
1721                                        } else {
1722                                                // it could be a timer
1723                                                hasOtherDefinitions = true;
1724                                        }
1725                                } else {
1726                                        // anything else
1727                                        hasOtherDefinitions = true;
1728                                        // search for local definition nodes
1729                                        //duplicated
1730                                        LinkedList<LocationAST> localDefNodes = new LinkedList<LocationAST>();
1731                                        for (int configuredLocalDefinitionType : configuredLocalDefinitionTypes){
1732                                                localDefNodes.addAll(ASTUtil
1733                                                        .findTypeNodes(controlStatementOrDefNode,
1734                                                                        configuredLocalDefinitionType));
1735                                        }
1736
1737                                       
1738                                        if (!localDefNodes.isEmpty()) {
1739                                                LocationAST localDefNode;
1740                                                for (int i = 0; i < localDefNodes.size(); i++) {
1741                                                        localDefNode = localDefNodes.get(i);
1742                                                        this.getLoggingInterface().logWarning(
1743                                                                        localDefNode.getLine(),
1744                                                                        localDefNode.getEndLine(),
1745                                                                        MessageClass.STYLE,
1746                                                                        "Local definition is not at the begining!",
1747                                                                        "6.8, " + MiscTools.getMethodName());
1748                                                }
1749
1750                                        }
1751
1752                                }
1753                        }
1754                } while ((controlStatementOrDefNode = controlStatementOrDefNode
1755                                .getNextSibling()) != null);
1756
1757        }
1758
1759        // -------------------------------------------------------------------------------------------
1760       
1761        private ArrayList<Integer> getConfiguredLocalDefinitionTypes() {
1762                ArrayList<Integer> configuredLocalDefinitionTypes = new ArrayList<Integer>();;
1763                for (String fieldName : T3Q.activeProfile
1764                                .getLocalDefinitionTypes()) {
1765                        if (!Arrays.asList(
1766                                        new QualityCheckProfile().getLocalDefinitionTypes())
1767                                        .contains(fieldName)) {
1768                                // TODO: error message
1769                        } else {
1770                                try {
1771                                        Class<TTCN3ParserTokenTypes> TTCN3TokenTypes = TTCN3ParserTokenTypes.class;
1772                                        Field field = TTCN3TokenTypes.getField(fieldName);
1773                                        configuredLocalDefinitionTypes.add(Integer.parseInt(field.get(TTCN3TokenTypes)
1774                                                        .toString()));
1775                                } catch (SecurityException e) {
1776
1777                                } catch (NoSuchFieldException e) {
1778                                        // TODO: error message
1779                                        // System.out.println("NO SUCH FIELD!");
1780                                } catch (IllegalArgumentException e) {
1781                                } catch (IllegalAccessException e) {
1782                                }
1783
1784                        }
1785                }
1786                return configuredLocalDefinitionTypes;
1787        }
1788
1789
1790        // -------------------------------------------------------------------------------------------
1791
1792        public void checkImportsComeFirst(LocationAST node) {
1793                boolean hasOtherDefinitions = false;
1794
1795                if ((node.getNextSibling() == null)
1796                                || (node.getNextSibling().getType() != TTCN3ParserTokenTypes.ModuleDefinitionsPart)) {
1797                        return;
1798                }
1799
1800                LocationAST moduleDefinitionsList = node.getNextSibling()
1801                                .getFirstChild();
1802
1803                LocationAST moduleDefinition = moduleDefinitionsList.getFirstChild();
1804
1805                do {
1806                        if (moduleDefinition.getFirstChild() != null) {
1807                                LocationAST definition = moduleDefinition.getFirstChild();
1808                                if (definition.getType() == TTCN3ParserTokenTypes.ImportDef) {
1809                                        if (hasOtherDefinitions) {
1810                                                this.getLoggingInterface().logWarning(
1811                                                                definition.getLine(),
1812                                                                definition.getEndLine(),
1813                                                                MessageClass.STRUCTURE,
1814                                                                "Import statement is not at the begining!",
1815                                                                "6.9, " + MiscTools.getMethodName());
1816                                        }
1817                                } else {
1818                                        hasOtherDefinitions = true;
1819                                }
1820                        }
1821                } while ((moduleDefinition = moduleDefinition.getNextSibling()) != null);
1822        }
1823
1824        // -------------------------------------------------------------------------------------------
1825
1826        public void checkNoAllKeywordInPortDefinitions(LocationAST node) {
1827                LocationAST identifierNode = node.getFirstChild();
1828                String identifierText = identifierNode.getFirstChild().getText();
1829                LinkedList<LocationAST> allKeywordNodes = ASTUtil.findTypeNodes(node,
1830                                TTCN3ParserTokenTypes.AllKeyword);
1831                if (!allKeywordNodes.isEmpty()) {
1832                        LocationAST allKeywordNode;
1833                        for (int i = 0; i < allKeywordNodes.size(); i++) {
1834                                allKeywordNode = allKeywordNodes.get(i);
1835                                this.getLoggingInterface().logWarning(
1836                                                allKeywordNode.getLine(),
1837                                                allKeywordNode.getEndLine(),
1838                                                MessageClass.STRUCTURE,
1839                                                "\"all\" keyword is used in the definition of port \""
1840                                                                + identifierText + "\"!",
1841                                                "4.2.1, " + MiscTools.getMethodName());
1842                        }
1843                }
1844
1845        }
1846
1847        // -------------------------------------------------------------------------------------------
1848
1849        public void checkLogStatementFormat(LocationAST node) {
1850                if (subsequentLogStatementNodes.contains(node)){
1851                        //skipping subsequently checked nodes
1852                        return;
1853                }
1854                int endLine = node.getEndLine();
1855                String logStatementText = getLogStatementText(node);
1856                if (T3Q.activeProfile.isProcessSubsequentLogStatementsAsOne()) {
1857                        LocationAST subsequentLogStatementNode = getSubsequentLogStatement(node);
1858                        while (subsequentLogStatementNode != null){
1859                                logStatementText += getLogStatementText(subsequentLogStatementNode);
1860                                endLine = subsequentLogStatementNode.getEndLine();
1861                                subsequentLogStatementNodes.add(subsequentLogStatementNode);
1862                                subsequentLogStatementNode = getSubsequentLogStatement(subsequentLogStatementNode);
1863                        }
1864                }
1865                checkLogFormat(node, logStatementText, endLine);
1866        }
1867
1868        // -------------------------------------------------------------------------------------------
1869       
1870        private LocationAST getSubsequentLogStatement(LocationAST logStatementNode) {
1871                LocationAST subsequentLogStatementNode = null;
1872                LocationAST nextStatement = logStatementNode.getNthParent(3)
1873                                .getNextSibling();
1874
1875                if ((nextStatement != null) && (nextStatement.getType() == TTCN3ParserTokenTypes.SemiColon)) {
1876                                nextStatement = nextStatement.getNextSibling();
1877                }
1878                if (nextStatement != null){
1879                        if (nextStatement.getType() == TTCN3ParserTokenTypes.FunctionStatement ||
1880                                        nextStatement.getType() == TTCN3ParserTokenTypes.ControlStatementOrDef) {
1881                                LocationAST thirdChild = nextStatement
1882                                                .getNthChild(3);
1883                                if (thirdChild != null
1884                                                && thirdChild.getType() == TTCN3ParserTokenTypes.LogStatement) {
1885                                        subsequentLogStatementNode = thirdChild;
1886                                }
1887                        }
1888                }
1889
1890                return subsequentLogStatementNode;
1891        }
1892
1893        // -------------------------------------------------------------------------------------------
1894       
1895        private String getLogStatementText(LocationAST node) {
1896                String logStatementText = "";
1897               
1898                LocationAST logItem = node.getFirstChild();
1899               
1900                do {
1901                        if (logItem.getFirstChild().getType()!=TTCN3ParserTokenTypes.TemplateInstance){
1902                                logStatementText += logItem.getFirstChild().getText();
1903                        } else {
1904                                //TODO: attempt to perform resolution
1905                                logStatementText += "";
1906                        }
1907                        logItem = logItem.getNextSibling();
1908                } while (logItem!=null && logItem.getType()==TTCN3ParserTokenTypes.LogItem);
1909                return logStatementText;
1910        }
1911
1912        // -------------------------------------------------------------------------------------------
1913
1914        public void checkLogItemFormat(LocationAST node) {
1915                String logItemText = node.getFirstChild().getText();
1916                checkLogFormat(node, logItemText, node.getEndLine());
1917        }
1918
1919        // -------------------------------------------------------------------------------------------
1920       
1921        private void checkLogFormat(LocationAST node, String logItemText, int endLine) {
1922                boolean problemOccured = false;
1923                String warning = "";
1924
1925                Pattern logPattern = Pattern.compile(T3Q.activeProfile
1926                                .getLogFormatRegExp(), Pattern.DOTALL);
1927                Matcher logMatcher = logPattern.matcher(logItemText);
1928
1929                if (!logMatcher.matches()) {
1930                        problemOccured = true;
1931                        warning = "Invalid log format (\"" + logItemText + "\")!";
1932                } else if (!logMatcher.group(1).equals("")) { // check if the first
1933                        // group is empty
1934                        // if not try to resolve the container identifier
1935                        String logItemContainerIdentifier = logMatcher.group(1);
1936
1937                        // check if it is a module definition
1938                        LocationAST moduleDefinitionNode = LocationAST
1939                                        .resolveParentsUntilType(node,
1940                                                        TTCN3ParserTokenTypes.ModuleDefinition);
1941
1942                        if (moduleDefinitionNode != null) {
1943
1944                                // check if it is a function def or altstep def or testcase def
1945                                int parentContainerType = moduleDefinitionNode.getFirstChild()
1946                                                .getType();
1947                                if (parentContainerType == TTCN3ParserTokenTypes.Visibility){
1948                                        parentContainerType = moduleDefinitionNode.getFirstChild().getNextSibling()
1949                                        .getType();
1950                                }
1951                                if (parentContainerType == TTCN3ParserTokenTypes.TestcaseDef
1952                                                || parentContainerType == TTCN3ParserTokenTypes.FunctionDef
1953                                                || parentContainerType == TTCN3ParserTokenTypes.AltstepDef) {
1954                                        LocationAST parentContainerNodeIdentifier = LocationAST.getModuleDefinitionIdentifiersList(moduleDefinitionNode).get(0);
1955                                        Symbol parentContainerSymbol = parentContainerNodeIdentifier.getFirstChild().getSymbol();
1956                                        String parentContainerSymbolName = parentContainerSymbol
1957                                                        .getName();
1958
1959                                        if (!parentContainerSymbolName
1960                                                        .equals(logItemContainerIdentifier)) {
1961                                                problemOccured = true;
1962                                                warning = "Log statement contains invalid container identifier (\""
1963                                                                + logItemContainerIdentifier
1964                                                                + "\", should be \""
1965                                                                + parentContainerSymbolName + "\")!";
1966                                        }
1967
1968                                } else {
1969                                        // not a testcase, a function or an altstep
1970                                        // is it possible at all? - probably not
1971                                }
1972
1973                        } else {
1974                                // it is a control part
1975                                moduleDefinitionNode = LocationAST.resolveParentsUntilType(node,
1976                                                TTCN3ParserTokenTypes.ModuleControlPart);
1977                                if (moduleDefinitionNode == null) {
1978                                        // else it is not a control part - is it possible? probably
1979                                        // not
1980                                }
1981                        }
1982
1983                }
1984
1985                if (problemOccured) {
1986                        this.getLoggingInterface().logWarning(node.getLine(), endLine, MessageClass.LOGGING, warning, "5.1. "+MiscTools.getMethodName());
1987                }
1988        }
1989
1990        // -------------------------------------------------------------------------------------------
1991
1992        public void checkTestcasesModuleImportsLibCommon_Sync(LocationAST node) {
1993                LocationAST identifierNode = (LocationAST) ASTUtil.findChild(node, TTCN3ParserTokenTypes.IDENTIFIER);
1994                String moduleName = identifierNode.getText();
1995                if ((!moduleName.contains("Testcases"))
1996                                || moduleName.contains("LibCommon_Sync")) {
1997                        return;
1998                }
1999
2000                boolean libCommonReferenceFound = false;
2001               
2002                //Identical part
2003                LinkedList<LocationAST> importDefNodes = ASTUtil
2004                .findTypeNodes(node.getParent(),
2005                                TTCN3ParserTokenTypes.ImportDef);
2006                for (int i = 0; i < importDefNodes.size(); i++) {
2007                        String importedModuleIdentifierText = ASTUtil.findChild(importDefNodes.get(i), TTCN3ParserTokenTypes.IDENTIFIER).getText();
2008                        if (importedModuleIdentifierText.contains("LibCommon_Sync")) {
2009                                libCommonReferenceFound = true;
2010                        }
2011                }
2012               
2013//TODO: Superseded by above version, check for correctness and discard odler version   
2014//              LocationAST moduleDefinitionsList = node.getNextSibling()
2015//                              .getFirstChild();
2016//              LocationAST moduleDefinition = moduleDefinitionsList.getFirstChild();
2017//              do {
2018//                      if (moduleDefinition.getFirstChild() != null) {
2019//                              LocationAST definition = moduleDefinition.getFirstChild();
2020//                              if (definition.getType() == TTCN3ParserTokenTypes.ImportDef) {
2021//                                      LinkedList<LocationAST> importIdentifierNodes = ASTUtil
2022//                                                      .findTypeNodes(definition,
2023//                                                                      TTCN3ParserTokenTypes.Identifier);
2024//                                      for (int i = 0; i < importIdentifierNodes.size(); i++) {
2025//                                              if (importIdentifierNodes.get(i).getFirstChild()
2026//                                                              .getText().contains("LibCommon_Sync")) {
2027//                                                      LocationAST importFromSpecNode = LocationAST
2028//                                                                      .resolveParentsUntilType(
2029//                                                                                      importIdentifierNodes.get(i),
2030//                                                                                      TTCN3ParserTokenTypes.ImportFromSpec);
2031//                                                      if (importFromSpecNode != null)
2032//                                                              libCommonReferenceFound = true;
2033//                                              }
2034//                                      }
2035//                              }
2036//                      }
2037//              } while ((moduleDefinition = moduleDefinition.getNextSibling()) != null);
2038
2039                if (!libCommonReferenceFound) {
2040                        this
2041                        .getLoggingInterface()
2042                        .logWarning(
2043                                        identifierNode.getLine(),
2044                                        identifierNode.getEndLine(),
2045                                        MessageClass.STYLE,
2046                                        "Required import from \"LibCommon_Sync\" not found!",
2047                                        "7.11, " + MiscTools.getMethodName());
2048                }
2049        }
2050
2051        // -------------------------------------------------------------------------------------------
2052
2053        public void checkTypesAndValuesModuleImportsLibCommon(LocationAST node) {
2054                LocationAST identifierNode = (LocationAST) ASTUtil.findChild(node, TTCN3ParserTokenTypes.IDENTIFIER);
2055                String moduleName = identifierNode.getText();
2056
2057                Pattern typesAndValuesImportsLibNamesExcludedPattern = Pattern.compile(T3Q.activeProfile
2058                                .getTypesAndValuesImportsLibNamesExcludedRegExp());
2059                Matcher typesAndValuesImportsLibNamesExcludedMatcher = typesAndValuesImportsLibNamesExcludedPattern.matcher(moduleName);;
2060               
2061                if (!moduleName.contains("TypesAndValues")
2062                                || typesAndValuesImportsLibNamesExcludedMatcher.matches())
2063                        return;
2064
2065                Pattern typesAndValuesImportsLibNamesPattern = Pattern.compile(T3Q.activeProfile
2066                                .getTypesAndValuesImportsLibNamesRegExp());
2067                Matcher typesAndValuesImportsLibNamesMatcher = null;
2068               
2069                boolean libCommonReferenceFound = false;
2070
2071                LinkedList<LocationAST> importDefNodes = ASTUtil
2072                .findTypeNodes(node.getParent(),
2073                                TTCN3ParserTokenTypes.ImportDef);
2074                for (int i = 0; i < importDefNodes.size(); i++) {
2075                        String importedModuleIdentifierText = ASTUtil.findChild(importDefNodes.get(i), TTCN3ParserTokenTypes.IDENTIFIER).getText();
2076                        typesAndValuesImportsLibNamesMatcher = typesAndValuesImportsLibNamesPattern.matcher(importedModuleIdentifierText);
2077                        if (typesAndValuesImportsLibNamesMatcher.matches()) {
2078                                libCommonReferenceFound = true;
2079                        }
2080                }
2081
2082//TODO: Superseded by above version, check for correctness and discard odler version   
2083//              LocationAST moduleDefinitionsList = node.getNextSibling()
2084//                              .getFirstChild();
2085//              LocationAST moduleDefinition = moduleDefinitionsList.getFirstChild();
2086//              do {
2087//                      if (moduleDefinition.getFirstChild() != null) {
2088//                              LocationAST definition = moduleDefinition.getFirstChild();
2089//                              if (definition.getType() == TTCN3ParserTokenTypes.ImportDef) {
2090//                                      LocationAST importIdentifierNode = definition.getNthChild(4);
2091//                                      LinkedList<LocationAST> importIdentifierNodes = ASTUtil
2092//                                                      .findTypeNodes(definition,
2093//                                                                      TTCN3ParserTokenTypes.Identifier);
2094//                                      for (int i = 0; i < importIdentifierNodes.size(); i++) {
2095//                                              String identifierText = importIdentifierNodes.get(i).getFirstChild()
2096//                                                              .getText();
2097//                                              typesAndValuesImportsLibNamesMatcher = typesAndValuesImportsLibNamesPattern.matcher(identifierText);
2098//                                              if (typesAndValuesImportsLibNamesMatcher.matches()) {
2099//                                                      LocationAST importFromSpecNode = LocationAST
2100//                                                                      .resolveParentsUntilType(
2101//                                                                                      importIdentifierNodes.get(i),
2102//                                                                                      TTCN3ParserTokenTypes.ImportFromSpec);
2103//                                                      if (importFromSpecNode != null)
2104//                                                              libCommonReferenceFound = true;
2105//                                              }
2106//                                      }
2107//                              }
2108//                      }
2109//              } while ((moduleDefinition = moduleDefinition.getNextSibling()) != null);
2110
2111                if (!libCommonReferenceFound) {
2112                        this
2113                        .getLoggingInterface()
2114                        .logWarning(
2115                                        identifierNode.getLine(),
2116                                        identifierNode.getEndLine(),
2117                                        MessageClass.STYLE,
2118                                        "Required import from \""+T3Q.activeProfile.getTypesAndValuesImportsLibNamesRegExp()+"\" not found!!",
2119                                        "7.3, " + MiscTools.getMethodName());
2120                       
2121                }
2122        }
2123
2124        // -------------------------------------------------------------------------------------------
2125        //TODO: address wolfgang's problem
2126        public void checkNoModifiedTemplateOfModifiedTemplate(LocationAST node) {
2127                // Not explicitly necessary, for consistency only
2128                boolean problemOccured = false;
2129
2130                // resolution of the modified template scope
2131                LocationAST identifierNode = (LocationAST) ASTUtil.findChild(node,
2132                                TTCN3ParserTokenTypes.IDENTIFIER);
2133
2134                Symbol modifiedSymbol = identifierNode.getSymbol();
2135
2136                if (modifiedSymbol != null) {
2137
2138                        // derives the identifier of the declaration node
2139                        LocationAST modifiedIdentifierNode = modifiedSymbol
2140                                        .getDeclarationNode();
2141
2142                        // resolution of the declaration node
2143                        LocationAST modifiedTemplateNode = LocationAST.resolveParentsUntilType(modifiedIdentifierNode, TTCN3ParserTokenTypes.TemplateDef);
2144                        LocationAST modifiedTemplateDerivedDefNode = (LocationAST) ASTUtil
2145                                        .findDerivedDef(modifiedTemplateNode);
2146
2147                        if (modifiedTemplateDerivedDefNode != null) {
2148                                problemOccured = true;
2149
2150                                // resolution of the modifying template scope
2151                                //TODO: revise
2152                               
2153                                LocationAST modifyingIdentifierNode = node.getContainingModuleDefinitionIdentifiersList().get(0);
2154                                System.out.println(modifyingIdentifierNode);
2155                                Symbol modifyingSymbol = modifyingIdentifierNode.getFirstChild().getSymbol();
2156
2157                                if (problemOccured) {
2158                                        this
2159                                                        .getLoggingInterface()
2160                                                        .logWarning(
2161                                                                        node.getLine(),
2162                                                                        node.getEndLine(),
2163                                                                        MessageClass.STYLE,
2164                                                                        "Template \""
2165                                                                                        + modifyingSymbol.getName()
2166                                                                                        + "\" modifies another modified template (\""
2167                                                                                        + modifiedSymbol.getName() + "\")!",
2168                                                                        "6.7, " + MiscTools.getMethodName());
2169                                }
2170
2171                        }
2172                } else {
2173                        this
2174                        .getLoggingInterface()
2175                        .logInformation(
2176                                        identifierNode.getLine(),
2177                                        identifierNode.getEndLine(),
2178                                        MessageClass.STYLE,
2179                                        "The declaration of template \""
2180                                        + identifierNode.getText()
2181                                        + "\" cannot be resolved! It cannot be determined whether it is a modified template.",
2182                                        "6.7, " + MiscTools.getMethodName());
2183                }
2184
2185        }
2186
2187        // -------------------------------------------------------------------------------------------
2188
2189        public void checkNoNestedAltStatements(LocationAST node) {
2190
2191
2192                LinkedList<LocationAST> nestedAltConstructNodes = ASTUtil.findTypeNodes(node
2193//                              .getFirstChild()
2194                                , TTCN3ParserTokenTypes.AltConstruct);
2195
2196                if (nestedAltConstructNodes != null && nestedAltConstructNodes.size() > 0) {
2197                        LocationAST nestedAltConstructNode;
2198
2199                        for (int n = 0; n < nestedAltConstructNodes.size(); n++) {
2200                                nestedAltConstructNode = nestedAltConstructNodes.get(n);
2201                                int nestingDepth = getAltConstructNesting(nestedAltConstructNode);
2202                                if (nestingDepth > T3Q.activeProfile.getMaximumAllowedNestingDepth()) {
2203                                        this.getLoggingInterface().logWarning(nestedAltConstructNode.getLine(), nestedAltConstructNode.getEndLine(), MessageClass.STYLE, "Alt statement nesting depth ("+nestingDepth+") exceeds maximum allowed nesting depth ("+T3Q.activeProfile.getMaximumAllowedNestingDepth()+")!", "6.3, "+MiscTools.getMethodName());
2204                                }
2205                        }
2206                }
2207
2208        }
2209
2210        // -------------------------------------------------------------------------------------------
2211
2212        private int getAltConstructNesting(LocationAST node){
2213                int nestingDepth = 1;
2214                LocationAST containingAltConstructNode = LocationAST.resolveParentsUntilType(node.getParent(), new int[] {TTCN3ParserTokenTypes.AltConstruct, TTCN3ParserTokenTypes.AltstepDef});
2215               
2216                if (containingAltConstructNode != null){
2217                        nestingDepth += getAltConstructNesting(containingAltConstructNode);
2218                } else {
2219                        nestingDepth = 0;
2220                }
2221                return nestingDepth;
2222        }
2223       
2224        // -------------------------------------------------------------------------------------------
2225
2226        public void checkNoAnyTypeKeyword(LocationAST node) {
2227                // Not explicitly necessary, for consistency only
2228                boolean problemOccured = false;
2229                problemOccured = true;
2230                if (problemOccured) {
2231                        this.getLoggingInterface().logWarning(node.getLine(), node.getEndLine(), MessageClass.STYLE, "Keyword \"anytype\" is used!", "6.5, "+MiscTools.getMethodName());
2232                }
2233
2234        }
2235
2236        // -------------------------------------------------------------------------------------------
2237
2238        public void checkNoGotoStatements(LocationAST node) {
2239                // Not explicitly necessary, for consistency only
2240                boolean problemOccured = false;
2241                problemOccured = true;
2242                if (problemOccured) {
2243                        this.getLoggingInterface().logWarning(node.getLine(), node.getEndLine(), MessageClass.STYLE, "A \"goto\" statement is used!", "6.1, "+MiscTools.getMethodName());
2244                }
2245
2246        }
2247
2248        // -------------------------------------------------------------------------------------------
2249
2250        public void checkNoLabelStatements(LocationAST node) {
2251                // Not explicitly necessary, for consistency only
2252                boolean problemOccured = false;
2253                problemOccured = true;
2254                if (problemOccured) {
2255                        this.getLoggingInterface().logWarning(node.getLine(), node.getEndLine(), MessageClass.STYLE, "A \"label\" statement is used!", "6.1, "+MiscTools.getMethodName());
2256                }
2257
2258        }
2259
2260        // -------------------------------------------------------------------------------------------
2261
2262        public void checkExternalFunctionInvocationPrecededByLogStatement(
2263                        LocationAST node) {
2264
2265                LocationAST identifierNode = (LocationAST) ASTUtil.findChild(node,
2266                                TTCN3ParserTokenTypes.Identifier);
2267
2268                Symbol symbol = identifierNode.getFirstChild().getSymbol();
2269
2270                // TODO: fix
2271                // ETSI SIP/ETSI TS 102 027-3
2272                // (SIP) -v4.2.5 (2008-01)/SIP_Steps.ttcn
2273                // : Function Call to Response_401_r_1 on Line:12830
2274                // PROBLEM: Symbol scope cannot be determined.
2275
2276                if (symbol == null) {
2277                        this.getLoggingInterface().logInformation(node.getLine(),
2278                                        node.getEndLine(),
2279                                        MessageClass.LOGGING,
2280                                        "Function definition for \""
2281                                                        + identifierNode.getFirstChild().getText()
2282                                                        + "\" cannot be resolved! It cannot be determined if it is an external function call!",
2283                                        "5.3, " + MiscTools.getMethodName());
2284                       
2285                }
2286               
2287                if (symbol instanceof FunctionSymbol) {
2288                        FunctionSymbol fs = (FunctionSymbol) symbol;
2289
2290                        if (fs.isExternal()) {
2291                                boolean problemOccured = false;
2292                                String symbolName = fs.getName();
2293
2294                                LocationAST parentNode = LocationAST.resolveParentsUntilType(node,
2295                                                TTCN3ParserTokenTypes.FunctionStatement);
2296
2297                                if (parentNode == null) {
2298                                        LocationAST moduleDefinitionNode = LocationAST.resolveParentsUntilType(node,
2299                                                        TTCN3ParserTokenTypes.ModuleDefinition);
2300                                        if (moduleDefinitionNode != null) {
2301
2302                                                this.getLoggingInterface().logInformation(node.getLine(),
2303                                                                node.getEndLine(),
2304                                                                MessageClass.LOGGING,
2305                                                                "Call to external function \""
2306                                                                                + symbolName
2307                                                                                + "\" within a definition on the module level. It cannot be preceded by a log statement!",
2308                                                                "5.3, " + MiscTools.getMethodName());
2309
2310                                        } else {
2311                                                // TODO: produce a debugging message?
2312                                        }
2313                                        return;
2314                                }
2315
2316                                int functionStatementOrDefsVisitedCount = visitor       .getFunctionStatementOrDefNodes()
2317                                                                                                                                        .size();
2318                                if (parentNode == visitor       .getFunctionStatementOrDefNodes()
2319                                                                                        .get(functionStatementOrDefsVisitedCount - 1)) {
2320
2321                                        int i = functionStatementOrDefsVisitedCount - 2;
2322                                        if (i >= 0) {
2323                                                LocationAST next = null;
2324                                                // skip semicolons
2325                                                next = visitor  .getFunctionStatementOrDefNodes()
2326                                                                                .get(i)
2327                                                                                .getNextSibling();
2328
2329                                                while ((next != null)
2330                                                                && (next.getType() == TTCN3ParserTokenTypes.SemiColon)) {
2331                                                        next = next.getNextSibling();
2332                                                }
2333
2334                                                if (next == parentNode) {
2335                                                        LocationAST resultNode = (LocationAST) ASTUtil.findChild(visitor.getFunctionStatementOrDefNodes()
2336                                                                                                                                                                                        .get(i),
2337                                                                        TTCN3ParserTokenTypes.LogStatement);
2338                                                        if (resultNode == null) {
2339                                                                problemOccured = true;
2340                                                        }
2341                                                } else {
2342                                                        problemOccured = true;
2343                                                }
2344                                        } else {
2345                                                problemOccured = true;
2346                                        }
2347                                }                               
2348                               
2349//                              LocationAST parentSibling = parentNode.getNextSibling();
2350//
2351//                              // Check if there is a next sibling and if it is a SemiColon
2352//                              if (parentSibling != null
2353//                                              && parentSibling.getType() == TTCN3ParserTokenTypes.SemiColon) {
2354//                                      // Next sibling is a SemiColon, skip to the next one
2355//                                      parentSibling = parentSibling.getNextSibling();
2356//                              }
2357//
2358//                              if (parentSibling != null) {
2359//
2360//                                      if (parentSibling.getType() == TTCN3ParserTokenTypes.FunctionStatement) {
2361//                                              if (ASTUtil.findTypeNodes(parentSibling,
2362//                                                              TTCN3ParserTokenTypes.LogStatement).isEmpty()) {
2363//                                                      // fixed: consider using ASTUtil.findChild instead
2364//                                                      // => not for now
2365//
2366//                                                      // Sibling does not contain a log statement
2367//                                                      problemOccured = true;
2368//
2369//                                              }
2370//                                      } else {
2371//                                              // Sibling not of type FunctionStateme -> no Log
2372//                                              // statement present
2373//                                              problemOccured = true;
2374//                                      }
2375//                              } else {
2376//                                      // No sibling present -> no Log statement present
2377//                                      problemOccured = true;
2378//
2379//                              }
2380
2381                                if (problemOccured) {
2382                                        this.getLoggingInterface().logWarning(node.getLine(),
2383                                                        node.getEndLine(),
2384                                                        MessageClass.LOGGING,
2385                                                        "Call to external function \"" + symbolName
2386                                                                        + "\" not preceded by a log statement!",
2387                                                        "5.3, " + MiscTools.getMethodName());
2388                                }
2389
2390                        } else {
2391                                // Symbol Not a Function Symbol
2392                        }
2393                }
2394        }
2395       
2396        // -------------------------------------------------------------------------------------------
2397       
2398        public void checkInconcOrFailSetVerdictPrecededByLog(LocationAST node) {
2399                //TODO: no more function statement or defs
2400                //TODO: fixed issue with statement blocks
2401               
2402                // Fixed: currently based on SetLocalVerdict node,
2403                // consider starting at the fail or inconc node instead, checking
2404                // whether it is
2405                // within a set verdict context and proceed from there
2406                // fix: it is specific to the set verdict and not to inconc or fail
2407                // alone
2408
2409                boolean problemOccured = false;
2410                if (ASTUtil.findChild(node, TTCN3ParserTokenTypes.Fail) != null
2411                                || ASTUtil.findChild(node, TTCN3ParserTokenTypes.Inconc) != null) {
2412
2413                        LocationAST parentNode = LocationAST.resolveParentsUntilType(node,
2414                                        new int[] {TTCN3ParserTokenTypes.FunctionStatement});
2415                        if (parentNode == null){
2416                                this.getLoggingInterface().logFix(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "Cannot resolve the parent node", "5.4, "+MiscTools.getMethodName());               
2417                                return;
2418                        }
2419
2420                        int functionStatementOrDefsVisitedCount = visitor
2421                                        .getFunctionStatementOrDefNodes().size();
2422                        if (parentNode == visitor.getFunctionStatementOrDefNodes().get(
2423                                        functionStatementOrDefsVisitedCount - 1)) {
2424
2425                                int i = functionStatementOrDefsVisitedCount - 2;
2426                                if (i >= 0) {
2427                                        LocationAST next = null;
2428                                        // skip semicolons
2429                                        next = visitor.getFunctionStatementOrDefNodes().get(i)
2430                                                        .getNextSibling();
2431
2432                                        while ((next != null)
2433                                                        && (next.getType() == TTCN3ParserTokenTypes.SemiColon)) {
2434                                                next = next.getNextSibling();
2435                                        }
2436
2437                                        if (next == parentNode) {
2438                                                LocationAST resultNode = (LocationAST) ASTUtil
2439                                                                .findChild(visitor
2440                                                                                .getFunctionStatementOrDefNodes()
2441                                                                                .get(i),
2442                                                                                TTCN3ParserTokenTypes.LogStatement);
2443                                                if (resultNode == null) {
2444                                                        problemOccured = true;
2445                                                }
2446                                        } else {
2447                                                problemOccured = true;
2448                                        }
2449                                } else {
2450                                        problemOccured = true;
2451                                }
2452                        }
2453                }
2454
2455                if (problemOccured) {
2456                        this.getLoggingInterface().logWarning(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "No log statement precedes a fail or inconc setverdict statement!", "5.4, "+MiscTools.getMethodName());
2457                }
2458        }
2459
2460       
2461        //TODO: temporary duplicate of the above
2462        //- above needs refactoring
2463        //- this needs to be separated in a realtime checker
2464        public void checkWaitStatementPrecededByLog(LocationAST node) {
2465                // TODO: no more function statement or defs
2466                // TODO: fixed issue with statement blocks
2467
2468                // Fixed: currently based on SetLocalVerdict node,
2469                // consider starting at the fail or inconc node instead, checking
2470                // whether it is
2471                // within a set verdict context and proceed from there
2472                // fix: it is specific to the set verdict and not to inconc or fail
2473                // alone
2474
2475                boolean problemOccured = false;
2476                LocationAST parentNode = LocationAST.resolveParentsUntilType(node,
2477                                new int[] { TTCN3ParserTokenTypes.FunctionStatement });
2478                if (parentNode == null) {
2479                        this.getLoggingInterface().logFix(node.getLine(),
2480                                        node.getEndLine(),
2481                                        MessageClass.LOGGING,
2482                                        "Cannot resolve the parent node",
2483                                        "5.4, " + MiscTools.getMethodName());
2484                        return;
2485                }
2486
2487                int functionStatementOrDefsVisitedCount = visitor.getFunctionStatementOrDefNodes()
2488                                                                                                                        .size();
2489                if (parentNode == visitor.getFunctionStatementOrDefNodes()
2490                                                                        .get(functionStatementOrDefsVisitedCount - 1)) {
2491
2492                        int i = functionStatementOrDefsVisitedCount - 2;
2493                        if (i >= 0) {
2494                                LocationAST next = null;
2495                                // skip semicolons
2496                                next = visitor.getFunctionStatementOrDefNodes()
2497                                                                .get(i)
2498                                                                .getNextSibling();
2499
2500                                while ((next != null)
2501                                                && (next.getType() == TTCN3ParserTokenTypes.SemiColon)) {
2502                                        next = next.getNextSibling();
2503                                }
2504
2505                                if (next == parentNode) {
2506                                        LocationAST resultNode = (LocationAST) ASTUtil.findChild(visitor.getFunctionStatementOrDefNodes()
2507                                                                                                                                                                        .get(i),
2508                                                        TTCN3ParserTokenTypes.LogStatement);
2509                                        if (resultNode == null) {
2510                                                problemOccured = true;
2511                                        }
2512                                } else {
2513                                        problemOccured = true;
2514                                }
2515                        } else {
2516                                problemOccured = true;
2517                        }
2518                }
2519
2520                if (problemOccured) {
2521                        this.getLoggingInterface()
2522                                .logWarning(node.getLine(),
2523                                                node.getEndLine(),
2524                                                MessageClass.LOGGING,
2525                                                "No log statement precedes a wait statement!",
2526                                                "RT.X.X, " + MiscTools.getMethodName());
2527                }
2528        }
2529       
2530        // -------------------------------------------------------------------------------------------
2531
2532        public void checkNoPermutationKeyword(LocationAST node) {
2533                // Not explicitly necessary, for consistency only
2534                boolean problemOccured = false;
2535                problemOccured = true;
2536                if (problemOccured) {
2537                        this.getLoggingInterface().logWarning(node.getLine(), node.getEndLine(), MessageClass.STYLE, "Keyword \"permutation\" is used!", "6.4, "+MiscTools.getMethodName());
2538                }
2539
2540        }
2541
2542        // ---------------BASE REFERENCES - TO BE DISCARDED---------------------
2543
2544        // DEPRECATED: FOR REFERENCE ONLY
2545        public void checkExternalFunctionInvocationFollowedByLogStatementDEV(
2546                        LocationAST node) {
2547                // DEBUG
2548
2549                LocationAST identifierNode = (LocationAST) ASTUtil.findChild(node,
2550                                TTCN3ParserTokenTypes.IDENTIFIER);
2551
2552                Symbol symb = identifierNode.getScope().resolve(identifierNode);
2553
2554
2555                if (symb instanceof FunctionSymbol) {
2556                        FunctionSymbol fs = (FunctionSymbol) symb;
2557
2558                        // DEBUG
2559                        this.getLoggingInterface().logDebug(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "external: " + fs.isExternal());
2560
2561                       
2562                        if (fs.isExternal()) {
2563                                boolean problemOccured = false;
2564                                String symbolName = fs.getName();
2565                                LocationAST parentNode = LocationAST.resolveParentsUntilType(
2566                                                node, TTCN3ParserTokenTypes.FunctionStatement);
2567                                // DEBUG
2568                                this.getLoggingInterface().logDebug(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "Parent Type:"
2569                                                + parentNode.getType());
2570
2571                                this.getLoggingInterface().logDebug(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "Parent Text:"
2572                                                + parentNode.getText());
2573
2574                                // 2x getNextSibling to skip the SemiColon
2575                                LocationAST parentSibling = parentNode.getNextSibling()
2576                                                .getNextSibling();
2577
2578                                if (parentSibling != null) {
2579                                        // DEBUG
2580                                        this.getLoggingInterface().logDebug(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "Parent Sibling Type:"
2581                                                        + parentSibling.getType());
2582                                        this.getLoggingInterface().logDebug(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "Parent Sibling Text:"
2583                                                        + parentSibling.getText());
2584
2585                                        if (parentSibling.getType() == TTCN3ParserTokenTypes.FunctionStatement) {
2586                                                if (ASTUtil.findTypeNodes(parentSibling,
2587                                                                TTCN3ParserTokenTypes.LogStatement).isEmpty()) {
2588                                                        // DEBUG
2589                                                        this.getLoggingInterface().logDebug(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "Sibling does not containg a log statement!");
2590                                                        problemOccured = true;
2591
2592                                                }
2593                                        } else {
2594                                                // DEBUG
2595                                                this.getLoggingInterface().logDebug(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "Sibling not of Type FunctionStatement  => No Log Statement Present");
2596                                                problemOccured = true;
2597                                        }
2598                                } else {
2599                                        // DEBUG
2600                                        this.getLoggingInterface().logDebug(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "No Sibling Present! => No Log Statement Present");
2601                                        problemOccured = true;
2602
2603                                }
2604
2605                                if (problemOccured) {
2606                                        this.getLoggingInterface().logWarning(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "Call to external function \""
2607                                                        + symbolName
2608                                                        + "\" not followed by a log statement!", "5.4, "+ MiscTools.getMethodName());
2609                                }
2610
2611                        } else {
2612                                // DEBUG
2613                                this.getLoggingInterface().logDebug(node.getLine(), node.getEndLine(), MessageClass.LOGGING, "Symbol NOT a function symbol");
2614                        }
2615
2616                }
2617        }
2618
2619
2620
2621
2622}
Note: See TracBrowser for help on using the repository browser.