Tools__TagList.st
changeset 15855 e8cd02427e78
parent 15852 005d6c483bfa
child 15856 8436d7f427c9
child 15912 6edd447ce2c8
--- a/Tools__TagList.st	Sun Sep 20 12:28:32 2015 +0200
+++ b/Tools__TagList.st	Tue Sep 22 10:27:41 2015 +0200
@@ -2220,7 +2220,7 @@
 
 fromFile:aFile in:aTempDirectory
     "create tags from a file;
-     either use the ctags/etags command, or an intenral naive, simple method."
+     either use the ctags/etags command, or an internal naive, simple method."
 
     |forceSimpleTagList list shellCmd numTags fileContents|
 
@@ -2238,9 +2238,7 @@
         shellCmd notNil ifTrue:[
             tagTypesPresent := false.     "/ will be set again, when ctags command provides types
             list := self getTagListFromFile:aFile usingCommand:shellCmd mode:nil in:aTempDirectory.
-            (self class isCSuffix:(aFile suffix)) ifTrue:[
-                list addAll:(self additionalCTagsInFile:aFile)
-            ]
+            list addAll:(self getAdditionalCTagsInFile:aFile withList:list)
         ].
     ].
 
@@ -2713,103 +2711,6 @@
 
 !TagList methodsFor:'tag generation - simple'!
 
-additionalCTagsInFile:aFilePath
-    "additional tags, which are not found by the standard ctags utility:
-        case foo:   - case label tags
-        switch:     - case label tags
-        label:      - label tags (if there is a corresponding goto)
-    "
-
-    |targets line lineNr s caseLabel l gotoTargets possibleLabels|
-
-    self hideLabels ifTrue:[^ #()].
-    showOnly notNil ifTrue:[^ #()].
-
-    Tag autoload.
-
-    targets := OrderedCollection new.
-    gotoTargets := Set new.
-    possibleLabels := OrderedCollection new.
-
-    s := aFilePath asFilename readStream.
-    s notNil ifTrue:[
-        lineNr := 0.
-        s := LineNumberReadStream readingFrom:s.
-        [s atEnd] whileFalse:[
-            lineNr := lineNr + 1.
-            line := s nextLine withoutSeparators.
-            ((line startsWith:'case ') and:[line includes:$:]) ifTrue:[
-                l := line readStream. 
-                l skip:5.
-                caseLabel := l upTo:$:.
-                targets add:(Tag::TCaseLabel
-                                label:'case ' allItalic , caseLabel",' <case>' allItalic"
-                                pattern:nil
-                                type:nil
-                                lineNumber:lineNr).
-            ] ifFalse:[
-                (line startsWith:'default:') ifTrue:[
-                    targets add:(Tag::TCaseLabel
-                                    label:'case ' allItalic, 'default'
-                                    pattern:nil
-                                    type:nil
-                                    lineNumber:lineNr).
-                ] ifFalse:[
-                    ((line startsWith:'switch') and:[line includes:$(]) ifTrue:[
-                        l := line readStream. 
-                        l skip:6.
-                        l skipSeparators.
-                        l peek == $( ifTrue:[
-                            l next.
-                            caseLabel := (l upTo:$)) withoutSeparators.
-                            caseLabel notEmpty ifTrue:[
-                                caseLabel := 'switch (',caseLabel,')'.
-                                targets add:(Tag::TCaseLabel
-                                            label:'case ' allItalic , caseLabel
-                                            pattern:nil
-                                            type:nil
-                                            lineNumber:lineNr).
-                            ]
-                        ]
-                    ] ifFalse:[
-                        (line startsWith:'goto ') ifTrue:[
-                            |targetLabel|
-                            l := line readStream. 
-                            l skip:5.
-                            l skipSeparators.
-                            targetLabel := (l upTo:$; ) withoutSeparators.
-                            targetLabel notEmpty ifTrue:[
-                                gotoTargets add:targetLabel.
-                            ]
-                        ] ifFalse:[
-                            (line includes:$:) ifTrue:[
-                                |label|
-                                label := (line upTo:$:) withoutSeparators.
-                                label notEmpty ifTrue:[
-                                    ((label first isLetter or:[label first = $_])
-                                    and:[ label conform:[:ch | ch isLetterOrDigit or:[ch = $_]]]) ifTrue:[
-                                        possibleLabels 
-                                            add:(Tag::TCaseLabel
-                                                label:'label ' allItalic , label
-                                                pattern:label
-                                                type:nil
-                                                lineNumber:lineNr)
-                                    ].
-                                ].
-                            ].
-                        ].
-                    ]
-                ]
-            ].
-        ].
-        s close
-    ].
-    possibleLabels 
-        select:[:lbl | gotoTargets includes:lbl pattern]
-        thenDo:[:lbl | targets add:lbl].
-    ^ targets
-!
-
 assemblerTagsInFile:aFilePath
     "assembler tags:
      naive, q&d scan for lines matching:
@@ -2982,6 +2883,142 @@
     "Modified: / 22-08-2012 / 21:32:33 / cg"
 !
 
+getAdditionalCTagsInFile:aFilePath withList:ctagsList
+    "additional tags, which are not found by the standard ctags utility:
+        case foo:   - case label tags
+        switch:     - case label tags
+        label:      - label tags (if there is a corresponding goto)
+
+     The already generated ctagsList is passed as argument,
+     so duplicates etc. can be detected"
+
+    |targets line lineNr s caseLabel l gotoTargets possibleLabels 
+     addLabelTag findCurrentFunctionPrefix|
+
+    self hideLabels ifTrue:[^ #()].
+    showOnly notNil ifTrue:[^ #()].
+
+    Tag autoload.
+
+    targets := OrderedCollection new.
+    gotoTargets := Set new.
+    possibleLabels := OrderedCollection new.
+
+    findCurrentFunctionPrefix :=
+        [:lineNr |
+            |bestSoFar|
+
+            ctagsList do:[:each |
+                each isFunctionOrMethodTag ifTrue:[
+                    each lineNumber <= lineNr ifTrue:[
+                        (bestSoFar isNil or:[ each lineNumber > bestSoFar lineNumber]) ifTrue:[
+                            bestSoFar := each
+                        ]
+                    ].
+                ].
+            ].
+            bestSoFar isNil
+                ifTrue:[ '' ]
+                ifFalse:[ bestSoFar label, ' ' ]
+        ].
+
+    addLabelTag := 
+        [:tagType :lineNr :label |
+            |fnPrefix|
+
+            fnPrefix := findCurrentFunctionPrefix value:lineNr.
+            targets add:(tagType
+                            label:(fnPrefix,label)
+                            pattern:nil
+                            type:nil
+                            lineNumber:lineNr).
+        ].
+
+    s := aFilePath asFilename readStream.
+    s notNil ifTrue:[
+        lineNr := 0.
+        s := LineNumberReadStream readingFrom:s.
+        [s atEnd] whileFalse:[
+            lineNr := lineNr + 1.
+            line := s nextLine withoutSeparators.
+            ((line startsWith:'case ') and:[line includes:$:]) ifTrue:[
+                l := line readStream. 
+                l skip:5.
+                caseLabel := l upTo:$:.
+                addLabelTag value:(Tag::TCaseLabel) value:lineNr 
+                            value:('case ' allItalic , caseLabel",' <case>' allItalic").
+            ] ifFalse:[
+                (line startsWith:'default:') ifTrue:[
+                    addLabelTag value:(Tag::TCaseLabel) value:lineNr 
+                                value:('case ' allItalic, 'default').
+                ] ifFalse:[
+                    ((line startsWith:'switch') and:[line includes:$(]) ifTrue:[
+                        l := line readStream. 
+                        l skip:6.
+                        l skipSeparators.
+                        l peek == $( ifTrue:[
+                            l next.
+                            caseLabel := (l upTo:$)) withoutSeparators.
+                            caseLabel notEmpty ifTrue:[
+                                caseLabel := 'switch (',caseLabel,')'.
+                                addLabelTag value:(Tag::TCaseLabel) value:lineNr 
+                                            value:('case ' allItalic , caseLabel).
+                            ]
+                        ]
+                    ] ifFalse:[
+                        (line startsWith:'goto ') ifTrue:[
+                            |targetLabel|
+                            l := line readStream. 
+                            l skip:5.
+                            l skipSeparators.
+                            targetLabel := (l upTo:$; ) withoutSeparators.
+                            targetLabel notEmpty ifTrue:[
+                                gotoTargets add:targetLabel.
+                            ]
+                        ] ifFalse:[
+                            (line includes:$:) ifTrue:[
+                                |label|
+                                label := (line upTo:$:) withoutSeparators.
+                                label notEmpty ifTrue:[
+                                    ((label first isLetter or:[label first = $_])
+                                    and:[ label conform:[:ch | ch isLetterOrDigit or:[ch = $_]]]) ifTrue:[
+                                        |fnPrefix|
+                                        fnPrefix := findCurrentFunctionPrefix value:lineNr.
+                                        possibleLabels 
+                                            add:(Tag::TCaseLabel
+                                                label:(fnPrefix,('label ' allItalic , label))
+                                                pattern:label
+                                                type:nil
+                                                lineNumber:lineNr)
+                                    ].
+                                ].
+                            ].
+                        ].
+                    ]
+                ]
+            ].
+        ].
+        s close
+    ].
+    possibleLabels 
+        select:[:lbl | gotoTargets includes:lbl pattern]
+        thenDo:[:lbl | targets add:lbl].
+    ^ targets
+!
+
+getAdditionalTagsInFile:aFile withList:ctagsList
+    "a chance to generate a list of additional tags,    
+     which are not found by the standard ctags utility.
+     For example, for C, labels and switches are detected and added.
+     The already generated ctagsList is passed as argument,
+     so duplicates etc. can be detected"
+
+    (self class isCSuffix:(aFile suffix)) ifTrue:[
+        ^ self getAdditionalCTagsInFile:aFile withList:ctagsList
+    ].
+    ^ #()
+!
+
 getSimpleTagListFromFile:aFileOrString in:aTempDirectory
     "fallback, if no ctags is present, or if the file is not a c-file.
      Implemented here for some other file types (Makefiles)