Wiki

Ticket #111: utilsToExtns.patch

File utilsToExtns.patch, 34.6 KB (added by hopscc, 9 years ago)
  • Source/TypeProxies.cobra

     
    380380        Also, implements -correct-source:case or suggests it if it is off, but would have resolved. 
    381381        """ 
    382382        # don't need to check "basic types" like int, bool, etc. here. the parser does those. 
    383         if Utils.isCapped(name) 
     383        if name.isCapped 
    384384            symbol = .compiler.symbolForName(name, true, false)  # nested enum and class types are capped and can be members of the current class 
    385385        else 
    386386            symbol = nil 
    387387        if symbol is nil 
    388388            correctCase = 'case' in .compiler.options.setValue('correct-source') 
    389389            if correctCase 
    390                 if not Utils.isCapped(name) 
     390                if not name.isCapped 
    391391                    # not very sophisticated, but catches 'string', 'object', etc. 
    392392                    name = name.capped 
    393393                    symbol = .compiler.symbolForName(name, true, false) 
     
    399399                        .compiler.correctSource(.token, name) 
    400400            if symbol is nil 
    401401                sugg = Compiler.suggestionFor(name) ? '' 
    402                 if sugg == '' and not Utils.isCapped(name) 
     402                if sugg == '' and not name.isCapped 
    403403                    other = .compiler.symbolForName(name.capped, true, false) 
    404404                    if other, sugg = name.capped 
    405405                if sugg <> '', sugg = ' Try "[sugg]". Also, consider the -correct-source option (see cobra -h for details).' 
  • Source/Expr.cobra

     
    860860        """ 
    861861 
    862862    cue init(token as IToken, name as String, args as List<of Expr>, definition as EnumDecl) 
    863         require Utils.isCapped(name) 
     863        require name.isCapped 
    864864        base.init(token) 
    865865        _name = name 
    866866        _args = args 
  • Source/Parser.cobra

     
    145145        if _willShowTokens 
    146146            print 'expect([whatTypes]) --> [t]' 
    147147        if t is nil 
    148             .throwError('Expecting [Utils.join(" or ",whatTypes)], but source ended suddenly.') 
     148            .throwError('Expecting [" or ".join(whatTypes)], but source ended suddenly.') 
    149149        if t.which not in whatTypes 
    150             .throwError('Expecting [Utils.join(" or ",whatTypes)], but got [t] instead.') 
     150            .throwError('Expecting [" or ".join(whatTypes)], but got [t] instead.') 
    151151        return t to ! 
    152152 
    153153    def optional(whatTypes as vari String) as IToken? 
  • Source/BackEndClr/SharpGenerator.cobra

     
    145145                backEndOptions += ' [optChar]target:[target]' 
    146146                # TODO: what is the output for a module? 
    147147                branch target 
    148                     on 'exe' or 'winexe', outName = Utils.forceExtension(outName, '.exe') 
    149                     on 'library', outName = Utils.forceExtension(outName, '.dll') 
    150                     on 'module', outName = Utils.forceExtension(outName, '.netmodule')  # http://msdn2.microsoft.com/en-us/library/58scf68s(VS.80).aspx 
     148                    on 'exe' or 'winexe', outName = Utils.pathForceExtension(outName, '.exe') 
     149                    on 'library', outName = Utils.pathForceExtension(outName, '.dll') 
     150                    on 'module', outName = Utils.pathForceExtension(outName, '.netmodule')  # http://msdn2.microsoft.com/en-us/library/58scf68s(VS.80).aspx 
    151151                    else, throw FallThroughException(target) 
    152152            else 
    153                 outName = Utils.forceExtension(outName, '.exe') 
     153                outName = Utils.pathForceExtension(outName, '.exe') 
    154154            _fullExeFileName = outName 
    155155 
    156156            delaySign = options.boolValue('delay-sign') 
     
    233233                # use Process class instead of CSharpCodeProvider because the user specified a path to a C# compiler 
    234234                p = System.Diagnostics.Process() 
    235235                p.startInfo.fileName = cscPath 
    236                 sharpFileNames = Utils.join(' ', for fileName in sharpFileNameList get '"' + fileName + '"') 
     236                sharpFileNames = ' '.join( for fileName in sharpFileNameList get '"' + fileName + '"') 
    237237                p.startInfo.arguments = '[backEndOptions] [sharpFileNames]' 
    238238                if _verbosity >= 2 
    239239                    print '[p.startInfo.fileName] [p.startInfo.arguments]' 
     
    281281                    # otherwise, the first element is the C# compilation line 
    282282                    if _verbosity >= 2 and cr.output.count > 0 
    283283                        print '>>', cr.output[0], '<<' 
    284                     output = if(cr.output.count==0, '', Utils.join('\n', cr.output[1:]).trim) 
     284                    output = if(cr.output.count==0, '', '\n'.join(cr.output[1:]).trim) 
    285285                    # trace output 
    286286                    _parseSharpCompilerOutput(output) 
    287287 
     
    396396        if false 
    397397            # kind of silly, but it works: 
    398398            d = Dictionary<of int, int>() 
    399             for i = 1 .. Utils.countChars(File.readAllText(_sharpFileName), c'\n')+1 
     399            for i in 1 : File.readAllText(_sharpFileName).countChars(c'\n')+1 
    400400                d[i] = i 
    401401            return d     
    402402        return nil 
     
    508508        } 
    509509        sep = '' 
    510510        for name in isNames 
    511             name = Utils.getSS(isNameCS to passthrough, name, name) to ! 
     511            name = Utils.dictGetVOD<of String>(isNameCS to passthrough, name, name) 
    512512            sw.write(sep) 
    513513            sw.write(name) 
    514514            sep = ' ' 
     
    14321432        wroteNames = Set<of String>() 
    14331433        sep = '' 
    14341434        for name in _isNames 
    1435             name = Utils.getSS(isNameCS, name, name) to ! 
     1435            name = Utils.dictGetVOD<of String>(isNameCS, name, name)# to ! 
    14361436            sw.write(sep) 
    14371437            sw.write(name) 
    14381438            sep = ' ' 
  • Source/BackEndClr/ScanClrType.cobra

     
    5454                    .warning(CobraWarning('Already have declaration "[clrType.name]" in namespace "[curNameSpace.fullName]".')) 
    5555                else 
    5656                    if type.isClass 
    57                         if type.name.startsWith('Extend_') and Utils.countChars(type.name, c'_') >= 2 
     57                        if type.name.startsWith('Extend_') and type.name.countChars(c'_') >= 2 
    5858                            curNameSpace.addDecl(Extension(clrType)) 
    5959                        else 
    6060                            curNameSpace.addDecl(Class(clrType)) 
  • Source/BackEndJvm/JavaGenerator.cobra

     
    114114        if false 
    115115            # kind of silly, but it works: 
    116116            d = Dictionary<of int, int>() 
    117             for i in 1 : Utils.countChars(File.readAllText(_javaFileName), c'\n')+1 
     117            for i in 1 : File.readAllText(_javaFileName).countChars(c'\n')+1 
    118118                d[i] = i 
    119119            return d     
    120120        return nil 
     
    229229        } 
    230230        sep = '' 
    231231        for name in isNames 
    232             name = Utils.getSS(isNameJava to passthrough, name, name) to ! 
     232            name = Utils.dictGetVOD<of String>(isNameJava to passthrough, name, name) 
    233233            sw.write(sep) 
    234234            sw.write(name) 
    235235            sep = ' ' 
  • Source/CobraTokenizer.cobra

     
    354354        assert tok.text.endsWith(' ') 
    355355        # this is okay on continued lines 
    356356        if .justDidLineContinuation 
    357             indentLevel = Utils.countChars(tok.text, c'\t') + Utils.countChars(tok.text, c' ') // 4 
     357            indentLevel = tok.text.countChars(c'\t') + tok.text.countChars(c' ') // 4 
    358358            return _processNumIndentLevels(indentLevel)  # will check continuation indentation rules 
    359359        else 
    360360            return .onINDENT_MIXED_TS(tok) 
     
    375375        return .onINDENT_MIXED_TS(tok) 
    376376 
    377377    def onINDENT_ALL_TABS(tok as IToken) as IToken? 
    378         numTabs = Utils.countChars(tok.text, c'\t') 
     378        numTabs = tok.text.countChars(c'\t') 
    379379        return _processNumIndentLevels(numTabs) 
    380380 
    381381    def onINDENT_ALL_SPACES(tok as IToken) as IToken? 
    382         numSpaces = Utils.countChars(tok.text, c' ') 
     382        numSpaces = tok.text.countChars(c' ') 
    383383        if numSpaces % 4 and not .justDidLineContinuation # yes, 4. hard coded, intentionally. 
    384384            # TODO: should really just record an error and take (numSpaces/4).round as the indent 
    385385            .throwError('Space-based indentation must be a multiple of 4. This line has a remainder of [numSpaces%4].') 
  • Source/Compiler.cobra

     
    567567            hasSpaces = any for a in argList where ' ' in a 
    568568            if hasSpaces 
    569569                argList = for arg in argList get if(' ' in arg, '"[arg]"', arg) 
    570             args += Utils.join(' ', argList)  
     570            args += ' '.join(argList)  
    571571            p.startInfo.arguments = args 
    572572        return p 
    573573 
  • Source/Tokenizer.cobra

     
    585585            if _sourceLine is nil 
    586586                # end of source 
    587587                return false 
    588             numLines = Utils.countChars(_sourceLine to !, c'\n') 
     588            numLines = (_sourceLine to !).countChars( c'\n') 
    589589            if numLines == 0 and _willAlwaysEndWithNewLine 
    590590                _sourceLine += "\n" 
    591591            #trace sourceLine 
  • Source/Boxes.cobra

     
    232232                assert ns is not ns.superNameSpace 
    233233                ns = ns.superNameSpace 
    234234            nameSpaces.reverse 
    235             prefix = Utils.join('.', for ns in nameSpaces get ns.name) 
     235            prefix = '.'.join( for ns in nameSpaces get ns.name) 
    236236            if prefix.length 
    237237                prefix += '.' 
    238238            return prefix 
     
    533533    def _checkForInheritanceCycles(originalBox as Box, bases as Stack<of Box>) 
    534534        if this in bases 
    535535            names = for aBase in List<of Box>(Stack<of Box>(bases))[1:] get aBase.name 
    536             .throwError('Cyclical inheritance for "[.name]" with ancestor types [Utils.join(", ", names)] and back to [.name].') 
     536            .throwError('Cyclical inheritance for "[.name]" with ancestor types [", ".join(names)] and back to [.name].') 
    537537        else 
    538538            bases.push(this) 
    539539            if .baseClass, .baseClass._checkForInheritanceCycles(originalBox, bases) 
     
    861861            t = .memberwiseClone to Box 
    862862            assert t is not this 
    863863            genericDef._constructedTypes[key] = t 
    864             argNames = Utils.join(',', for type in typeArgs get type.name) 
     864            argNames = ','.join(for type in typeArgs get type.name) 
    865865            t._name = '[.rootName]<of [argNames]>' 
    866866            t._genericDef = this 
    867867            t._nativeType = nil  # The constructed type is really sourced from the generic def. Don't foster confusion with a reference to the original generic def's clr type (if there is one). 
  • Source/Cobra.Lang/Extensions.cobra

     
    2727            for i in chars.count, charsArray[i] = chars[i] 
    2828            return List<of String>(.split(charsArray)) 
    2929 
     30        # library String class join() only works on arrays of strings 
     31        def join(parts as System.Collections.IEnumerable) as String   # TODO: given that this seems necessary, should Cobra add "use System.Collections" to all programs? 
     32            """ 
     33            Join the items in an IEnumerable collection separated by this string 
     34            """ 
     35            test 
     36                assert '.'.join(['a', 'b'])=='a.b' 
     37                assert ' and '.join(['a', 'b'])=='a and b' 
     38            body 
     39                sep = this 
     40                sb = StringBuilder() 
     41                s = '' 
     42                for part in parts 
     43                    sb.append(s) 
     44                    sb.append(part.toString) 
     45                    s = sep 
     46                return sb.toString 
     47 
     48        def join(lastSep as String, parts as System.Collections.IEnumerable) as String 
     49            """ 
     50            Join the items of an IEnumerable collection with this string except for the last  
     51            two items; join them with the lastSep string 
     52            """ 
     53            test 
     54                assert ', '.join(' and ', ['a', 'b'])=='a and b' 
     55                assert ', '.join(' and ', ['a', 'b', 'c'])=='a, b and c' 
     56                assert ', '.join(' and ', ['a', 'b', 'c', 'd'])=='a, b, c and d' 
     57            body 
     58                sep = this 
     59                sb = StringBuilder() 
     60                s = '' 
     61                partsList = [] 
     62                for part in parts, partsList.add(part) 
     63                count = partsList.count 
     64                for i in count 
     65                    sb.append(s) 
     66                    sb.append(partsList[i].toString) 
     67                    s = if(i==count-2, lastSep, sep) 
     68                return sb.toString 
     69 
     70#       def join(sep as String, parts as vari String) as String  # CC: shouldn't need this because vari should implement IEnumerable 
     71#           return .join(sep, parts to System.Collections.IEnumerable) 
     72 
     73 
     74        def md5HashInHex as String 
     75            ensure 
     76                result.length == 32 
     77            test 
     78                assert 'Black holes and revelations.'.md5HashInHex == '95b141d670c19f2f20a820751897b9c6' 
     79            body 
     80                md5 = System.Security.Cryptography.MD5CryptoServiceProvider() 
     81                data = System.Text.Encoding.ascii.getBytes(this)  # why ASCII? why not utf8 or something? 
     82                data = md5.computeHash(data) 
     83                ret = '' 
     84                for i in data.length 
     85                    ret += data[i].toString('x2') 
     86                return ret 
     87 
     88        def countChars(c as char) as int 
     89            test 
     90                assert ''.countChars(c'x')==0 
     91                assert 'x'.countChars(c'x')==1 
     92                assert 'X'.countChars(c'x')==0  # case sensitive 
     93                assert ' ! ! '.countChars(c'!')==2 
     94            body 
     95                count = 0 
     96                for ch in this 
     97                    if c==ch 
     98                        count += 1 
     99                return count 
     100 
     101        def isCapped as bool 
     102            test 
     103                assert 'Aoeu'.isCapped 
     104                assert 'Zaoeu'.isCapped 
     105                assert not 'aoeu'.isCapped 
     106                assert not ''.isCapped 
     107                assert not '1234'.isCapped 
     108            body 
     109                return .length and this[0].isUpper 
     110 
     111        def capped as String 
     112            """ 
     113            Returns the string with the first character capitalized. 
     114            Returns a blank string for a blank string. 
     115            """ 
     116            ensure 
     117                result.length == .length 
     118                result.length implies result[0] == result[0].toUpper 
     119            test 
     120                assert 'chuck'.capped == 'Chuck' 
     121                assert 'Chuck'.capped == 'Chuck' 
     122                assert ''.capped == '' 
     123                assert ' foo'.capped == ' foo' 
     124                assert 'f'.capped == 'F' 
     125                assert '1aoeu'.capped == '1aoeu' 
     126            body 
     127                if .length == 0, return this 
     128                return this[0:1].toUpper + this[1:] 
     129             
     130        def startsIsLower as bool 
     131            require 
     132                .length 
     133            test 
     134                assert 'a'.startsIsLower 
     135                assert 'z'.startsIsLower 
     136                assert not 'A'.startsIsLower 
     137                assert not '1'.startsIsLower 
     138                assert not '_'.startsIsLower 
     139            body 
     140                return this[0].isLower 
     141 
     142        def startsIsNonLower as bool 
     143            require 
     144                .length 
     145            test 
     146                assert not 'a'.startsIsNonLower 
     147                assert not 'z'.startsIsNonLower 
     148                assert not '1'.startsIsNonLower 
     149                assert 'A'.startsIsNonLower 
     150            body 
     151                return this[0] <> this[0].toLower 
     152                 
     153 
    30154     
    31155    class DecimalTools 
    32156 
  • Source/CommandLine.cobra

     
    446446    """ 
    447447 
    448448    get versionString as String is shared 
    449         ensure Utils.countChars(result, c'.') == 2 
     449        ensure result.countChars(c'.') == 2 
    450450 
    451451        # Can't just take CobraCore.versionDescription as is, because that will be the one from Snapshot, 
    452452        # not the current Source directory. And Snapshot can be a final release such as '0.7.4' for a 
     
    858858        reMatch = Regex(r'\d+\.\d+\.\d+').match(.versionString) 
    859859        assert reMatch.success 
    860860        version = reMatch.value to ! 
    861         assert Utils.countChars(version, c'.') == 2  # ex: '0.8.0' 
     861        assert version.countChars(c'.') == 2  # ex: '0.8.0' 
    862862        if ' ' in .versionString or 'post' in .versionString  # ex: '0.8.0 post' 
    863863            # 'post' versions have a fourth version component of 1, as opposed to 0 
    864864            version += '.1' 
    865             assert Utils.countChars(version, c'.') == 3 
     865            assert version.countChars(c'.') == 3 
    866866        _options.addExtraUse('use System.Reflection') 
    867867        _options.addExtraSource("assembly\n\thas AssemblyVersion('[version]')\n") 
    868868        .doCompile(List<of String>(), true, false, false) 
     
    988988                        errMsg = 'Cannot parse value "[valueStr]" for option "[name]".' 
    989989                        branch spec.type 
    990990                            on 'bool', errMsg += ' Possible values include yes, no, y, n, true, false, t, f, 1, 0, + and -.' 
    991                             on 'menu', errMsg += ' Possible values are [Utils.join(", ", " and ", spec.choices)].' 
     991                            on 'menu', errMsg += ' Possible values are [", ".join(" and ", spec.choices)].' 
    992992                        _error(errMsg) 
    993993                    valueDict[name] = value to ! 
    994994                    didSpecify[name] = true 
     
    10071007            # TODO: make the option names case-insensitive 
    10081008 
    10091009            if mainOptions.count > 1 
    1010                 _error('Cannot have these main options at the same time: [Utils.join(", ", mainOptions)]') 
     1010                _error('Cannot have these main options at the same time: [", ".join(mainOptions)]') 
    10111011 
    10121012            _unpackOptions(valueDict, fileList)  
    10131013 
     
    10821082        """ 
    10831083        require name.trim <> '' 
    10841084        ensure result.trim <> '' 
    1085         name = Utils.getSS(_synToName to passthrough, name, name) to ! 
     1085        name = Utils.dictGetVOD<of String>(_synToName to passthrough, name, name) 
    10861086        assert name.trim <> '' 
    10871087        if not _specDict.containsKey(name) 
    10881088            msg = 'No such option "[name]".' 
  • Source/NameSpace.cobra

     
    114114                    t.add(ns.name) 
    115115                    ns = ns._superNameSpace 
    116116                t.reverse 
    117                 _fullName = Utils.join('.', t) 
     117                _fullName = '.'.join(t) 
    118118            return _fullName to ! 
    119119 
    120120    def getOrMakeNameSpaceNamed(token as IToken, name as String) as NameSpace  # CC: same 
     
    195195        for ns in _subNameSpacesList, ns.bindInh 
    196196 
    197197    def _checkCase 
    198         if Utils.startsWithLowerLetter(.name) and not .token.isEmpty 
     198        if .name.startsIsLower and not .token.isEmpty 
    199199            # TODO: make this an error eventually. warning added 2009-01-04 
    200200            .compiler.warning(this, 'Namespace names should start with an uppercase letter in order to avoid collisions with other identifiers such as arguments and local variables.') 
    201201 
     
    212212                    for n in sameNames, remainingNames.remove(n) 
    213213                    # at this point we have, for example, ['Foo', 'foo', 'FOO'] 
    214214                     
    215                     namesMsgPart = Utils.join(' ', for n in sameNames get '"[n]"') + '.' 
     215                    namesMsgPart = ' '.join(for n in sameNames get '"[n]"') + '.' 
    216216                    if all for n in sameNames get _declsByName[n] inherits NameSpace 
    217217                        # namespaces can be spread across DLLs and source files in any combination, so they only get a warning 
    218218                        .compiler.warning(this, 'Multiple namespaces in "[.fullName]" differ only by case: ' + namesMsgPart) 
     
    289289                membersList = List<of IMember>(members) 
    290290                membersList.sort(do(a as IMember, b as IMember)) 
    291291                    return a.parentNameSpace.fullName.compareTo(b.parentNameSpace.fullName) 
    292                 spaces = Utils.join(', ', ' and ', for m in membersList get '"[m.parentNameSpace.fullName]"') 
     292                spaces = ', '.join(' and ', for m in membersList get '"[m.parentNameSpace.fullName]"') 
    293293                if .compiler and .compiler.nodeStack.peek inherits ISyntaxNode 
    294294                    node = .compiler.nodeStack.peek 
    295295                else 
     
    395395    cue init(token as IToken, nameParts as List<of String>, fileName as String?) 
    396396        base.init(token) 
    397397        _nameParts = nameParts 
    398         _fullName = Utils.join('.', nameParts) 
     398        _fullName = '.'.join(nameParts) 
    399399        _fileName = fileName ? '' 
    400400 
    401401    def addMinFields 
  • Source/Utils.cobra

     
    88 
    99extend String 
    1010 
    11     def capped as String 
    12         """ 
    13         Returns the string with the first character capitalized. 
    14         Returns a blank string for a blank string. 
    15         """ 
    16         ensure 
    17             result.length == .length 
    18             result.length implies result[0] == result[0].toUpper 
    19         test 
    20             assert 'chuck'.capped == 'Chuck' 
    21             assert 'Chuck'.capped == 'Chuck' 
    22             assert ''.capped == '' 
    23             assert ' foo'.capped == ' foo' 
    24             assert 'f'.capped == 'F' 
    25             assert '1aoeu'.capped == '1aoeu' 
    26         body 
    27             if .length == 0, return this 
    28             return this[0:1].toUpper + this[1:] 
    29  
    30     def md5HashInHex as String 
    31         ensure 
    32             result.length == 32 
    33         test 
    34             assert 'Black holes and revelations.'.md5HashInHex == '95b141d670c19f2f20a820751897b9c6' 
    35         body 
    36             md5 = System.Security.Cryptography.MD5CryptoServiceProvider() 
    37             data = System.Text.Encoding.ascii.getBytes(this)  # why ASCII? why not utf8 or something? 
    38             data = md5.computeHash(data) 
    39             ret = '' 
    40             for i in data.length 
    41                 ret += data[i].toString('x2') 
    42             return ret 
    43  
    4411    ## Language specific 
    4512 
    4613    def canBeUndottedMemberName as bool 
     
    5219        names are typically protected data fields or methods while the uppercase names would be 
    5320        enums or (in the future) nested boxes. 
    5421        """ 
    55         return .startsWith('_') or Utils.isCapped(this) 
     22        return .startsWith('_') or .isCapped 
    5623 
    5724 
    5825class Utils 
    5926 
    6027    shared 
    6128 
    62         def combinePaths(a as String, b as String) as String 
    63             """ 
    64             Same as Path.combine() but leaves no '\.\' or '/./' in the result. 
    65             """ 
    66             p = Path.combine(a, b) 
    67             good = Path.directorySeparatorChar.toString 
    68             bad = '[good].[good]' 
    69             p = p.replace(bad, good) 
    70             return p 
    71  
    72         def normalizePath(path as String) as String 
    73             while path.startsWith('.\\'), path = path[2:] 
    74             while path.startsWith('./'), path = path[2:] 
    75             return path 
    76  
    7729        def plural(items as System.Collections.ICollection) as String 
    7830            ensure 
    7931                result == '' or result == 's' 
     
    8840            # Could be made more sophisitcated in the future 
    8941            return name + 's' 
    9042 
    91         def isCapped(s as String) as bool 
    92             test 
    93                 assert Utils.isCapped('Aoeu') 
    94                 assert Utils.isCapped('Zaoeu') 
    95                 assert not Utils.isCapped('aoeu') 
    96                 assert not Utils.isCapped('') 
    97                 assert not Utils.isCapped('1234') 
    98             body 
    99                 return s.length and s[0].isUpper 
    100  
    101         def startsWithLowerLetter(s as String) as bool 
    102             require 
    103                 s.length 
    104             test 
    105                 assert Utils.startsWithLowerLetter('a') 
    106                 assert Utils.startsWithLowerLetter('z') 
    107                 assert not Utils.startsWithLowerLetter('A') 
    108                 assert not Utils.startsWithLowerLetter('1') 
    109                 assert not Utils.startsWithLowerLetter('_') 
    110             body 
    111                 return s[0].isLower 
    112  
    113         def startsNonLower(s as String) as bool 
    114             require 
    115                 s.length 
    116             test 
    117                 assert not Utils.startsNonLower('a') 
    118                 assert not Utils.startsNonLower('z') 
    119                 assert not Utils.startsNonLower('1') 
    120                 assert Utils.startsNonLower('A') 
    121             body 
    122                 return s[0] <> s[0].toLower 
    123  
    12443        def toIdentifier(s as String) as String 
    12544            test 
    12645                cases = [ 
     
    14059                        sb.append(c'_') 
    14160                return sb.toString 
    14261 
    143         # TODO: count should be a CobraCore util method 
    144         # TODO: count should be an extension method of String 
    145         def countChars(s as String, c as char) as int 
    146             test 
    147                 assert Utils.countChars('', c'x')==0 
    148                 assert Utils.countChars('x', c'x')==1 
    149                 assert Utils.countChars('X', c'x')==0  # case sensitive 
    150                 assert Utils.countChars(' ! ! ', c'!')==2 
    151             body 
    152                 count = 0 
    153                 for ch in s 
    154                     if c==ch 
    155                         count += 1 
    156                 return count 
    157  
    158         # CC: the getXX() methods should be one generic method 
    159  
    160         def getSB(d as Dictionary<of String, dynamic>, key as String, defaultValue as bool) as bool 
     62        # this should probably be an extension on Dictionary?? 
     63        def dictGetVOD<of T>(d as Dictionary<of String, T>, key as String, defaultValue as T) as T 
     64            """ 
     65            GetValueOrDefault genericised for return type. 
     66            Return the value for String key from Dictionary d or if none return provided  
     67            default value 
     68            """ 
    16169            if d.containsKey(key) 
    16270                return d[key] 
    16371            else 
    16472                return defaultValue 
    165  
    166         def getSI(d as Dictionary<of String, int>, key as String, defaultValue as int) as int 
    167             if d.containsKey(key) 
    168                 return d[key] 
    169             else 
    170                 return defaultValue 
    171  
    172         def getSS(d as Dictionary<of String, String?>, key as String, defaultValue as String?) as String? 
    173             if d.containsKey(key) 
    174                 return d[key] 
    175             else 
    176                 return defaultValue 
    177  
    178         def getSO(d as Dictionary<of String, Object>, key as String, defaultValue as Object?) as Object? 
    179             if d.containsKey(key) 
    180                 return d[key] 
    181             else 
    182                 return defaultValue 
    183  
    184         # CC: make join an extension method of String which already has a join() except that it only works on arrays of strings 
    185         def join(sep as String, parts as System.Collections.IEnumerable) as String  # TODO: given that this seems necessary, should Cobra add "use System.Collections" to all programs? 
    186             test 
    187                 assert Utils.join('.', ['a', 'b'])=='a.b' 
    188             body 
    189                 sb = StringBuilder() 
    190                 s = '' 
    191                 for part in parts 
    192                     sb.append(s) 
    193                     sb.append(part.toString) 
    194                     s = sep 
    195                 return sb.toString 
    196  
    197         # CC: make join an extension method of String which already has a join() except that it only works on arrays of strings 
    198         def join(sep as String, lastSep as String, parts as System.Collections.IEnumerable) as String 
    199             test 
    200                 assert Utils.join(', ', ' and ', ['a', 'b'])=='a and b' 
    201                 assert Utils.join(', ', ' and ', ['a', 'b', 'c'])=='a, b and c' 
    202                 assert Utils.join(', ', ' and ', ['a', 'b', 'c', 'd'])=='a, b, c and d' 
    203             body 
    204                 sb = StringBuilder() 
    205                 s = '' 
    206                 partsList = [] 
    207                 for part in parts, partsList.add(part) 
    208                 count = partsList.count 
    209                 for i in count 
    210                     sb.append(s) 
    211                     sb.append(partsList[i].toString) 
    212                     s = if(i==count-2, lastSep, sep) 
    213                 return sb.toString 
    214  
    215         def join(sep as String, parts as vari String) as String  # CC: shouldn't need this because vari should implement IEnumerable 
    216             return .join(sep, parts to System.Collections.IEnumerable) 
    217  
    218  
     73             
    21974        ## C# 
    22075         
    22176        def cobraNameForSharpMemberName(name as String) as String 
     
    291146                print '[lineNum]|[line]'  # CC: right align and pad 0 the lineNum 
    292147                lineNum += 1 
    293148 
    294         def forceExtension(fileName as String, extension as String) as String 
     149        # These (next 3 methods) would be better as static extension methods on the Path class  
     150        # but MS/C#/.Net doesnt support extending existing classes with *static* extension methods 
     151        # so they remain util methods albeit renamed. 
     152        def pathCombine(a as String, b as String) as String  
     153            """ 
     154            Same as Path.combine() but normalized such that it leaves no '\.\' or '/./' in the result. 
     155            """ 
     156            p = Path.combine(a, b) 
     157            good = Path.directorySeparatorChar.toString 
     158            bad = '[good].[good]' 
     159            p = p.replace(bad, good) 
     160            return p 
     161 
     162        def pathNormalizeLeading( path as String) as String 
     163            """ 
     164            Normalise this string as a path string removing any leading './' or '.\' 
     165            """ 
     166            while path.startsWith('.\\'), path = path[2:] 
     167            while path.startsWith('./'), path = path[2:] 
     168            return path 
     169 
     170        def pathForceExtension(fileName as String, extension as String) as String 
    295171            require 
    296172                fileName.length 
    297173                extension.length 
    298174            ensure 
    299175                result.endsWith(extension) 
    300176            test 
    301                 assert Utils.forceExtension('foo.csv', '.exe') == 'foo.exe' 
    302                 assert Utils.forceExtension('foo.csv', 'exe') == 'foo.exe' 
    303                 assert Utils.forceExtension('foo', '.exe') == 'foo.exe' 
    304                 assert Utils.forceExtension('foo', 'exe') == 'foo.exe' 
    305                 assert Utils.forceExtension('foo.bar.csv', '.exe') == 'foo.bar.exe' 
     177                assert Utils.pathForceExtension('foo.csv', '.exe') == 'foo.exe' 
     178                assert Utils.pathForceExtension('foo.csv', 'exe') == 'foo.exe' 
     179                assert Utils.pathForceExtension('foo', '.exe') == 'foo.exe' 
     180                assert Utils.pathForceExtension('foo', 'exe') == 'foo.exe' 
     181                assert Utils.pathForceExtension('foo.bar.csv', '.exe') == 'foo.bar.exe' 
    306182            body 
    307183                if not extension.startsWith('.') 
    308184                    extension = '.' + extension 
     
    323199            require path.length 
    324200            return .readKeyValues(path, File.openText(path), Console.out) 
    325201         
    326         def readKeyValues(sr as StreamReader, warnings as TextWriter) as Dictionary<of String, String> 
    327             return .readKeyValues(sr, Console.out) 
    328  
    329202        def readKeyValues(path as String, tw as TextReader, warnings as TextWriter) as Dictionary<of String, String> 
    330203            test 
    331204                nl = Environment.newLine 
  • Source/CobraParser.cobra

     
    242242                        textParts.add(tok.text) 
    243243                    else 
    244244                        .throwError('Expecting more doc string contents or the end of the doc string instead of [tok].') 
    245             text = Utils.join('', textParts) 
     245            text = ''.join(textParts) 
    246246            return text 
    247247        else if .optional('DOC_STRING_LINE') 
    248248            return .last.value to String 
     
    472472                    fileNameParts.add(id.text) 
    473473                    dot = .optional('DOT') 
    474474                    if not dot, break 
    475                 fileName = Utils.join('.', fileNameParts) 
     475                fileName = '.'.join(fileNameParts) 
    476476            else 
    477477                .throwError('Expecting a file name (sans extension, with or without quotes) after "from".') 
    478478            if fileName.endsWith('.dll') or fileName.endsWith('.exe') 
     
    780780                if expectComma 
    781781                    .expect('COMMA') 
    782782                ident = .expect('ID').text 
    783                 if Utils.startsWithLowerLetter(ident) 
     783                if ident.startsIsLower 
    784784                    .throwError('Generic parameter names must start with an uppercase letter in order to avoid collisions with other identifiers such as arguments and local variables.') 
    785785                params.add(GenericParam(ident)) 
    786786                expectComma = true 
     
    25952595            else if peek=='NOT' and .peek(+1).which=='IN' 
    25962596                op = 'NOTIN' 
    25972597            # handle precedence (and detect non-binary operators) 
    2598             binaryOpPrec = Utils.getSI(_binaryOpPrec, op ? peek, -1) 
     2598            binaryOpPrec = Utils.dictGetVOD<of int>(_binaryOpPrec, op ? peek, -1) 
    25992599            if binaryOpPrec==-1 or binaryOpPrec<precedence 
    26002600                break 
    26012601            # continue... 
     
    28782878                _spaceAgnostic 
    28792879            if .peek is nil 
    28802880                literal = {'RPAREN': ')', 'RBRACKET': ']'} 
    2881                 what = Utils.join(" or ", for t in terminators get '"[if(literal.containsKey(t), literal[t], t)]"') 
     2881                what = " or ".join(for t in terminators get '"[if(literal.containsKey(t), literal[t], t)]"') 
    28822882                .throwError('Expecting "," or [what].') 
    28832883            if .peek.which in terminators 
    28842884                .grab 
     
    29752975        if .opStack.count and .opStack.peek=='DOT' 
    29762976            return MemberExpr(nameToken) 
    29772977        if .peek.which=='AS' 
    2978             if not Utils.startsWithLowerLetter(name) 
     2978            if not name.startsIsLower 
    29792979                .throwError('Local variable declarations must start with a lowercase letter. This avoids collisions with other identifiers such as classes and enums.') 
    29802980            return AsExpr(.grab, nameToken, .typeId) 
    29812981        else 
     
    30173017                            sep = which 
    30183018                            break 
    30193019                    if sep is nil 
    3020                         .throwError('Expecting one of: [Utils.join(", ", separators)], but encountered [.peek.which]') 
     3020                        .throwError('Expecting one of: [", ".join(separators)], but encountered [.peek.which]') 
    30213021                if sep=='COLON' 
    30223022                    lastThingWasColon = true 
    30233023            if .peek.which=='RBRACKET' 
     
    31573157        nameToken = .expect('ID') 
    31583158        name = nameToken.text 
    31593159        if .peek.which=='AS' 
    3160             if not Utils.startsWithLowerLetter(name) 
     3160            if not name.startsIsLower 
    31613161                .throwError('Local variable declarations must start with a lowercase letter. This avoids collisions with other identifiers such as classes and enums.') 
    31623162            return AsExpr(.grab, nameToken, .typeId) 
    31633163        else 
     
    33723372        other = box.declForNameCI(name) 
    33733373        if other 
    33743374            .throwError('There is already another class member with the name "[other.name]". You must differentiate member names by more than just case.') 
    3375         if Utils.startsNonLower(name) 
     3375        if name.startsIsNonLower 
    33763376            .throwError('Property names must start with lowercase letters. ([name])') 
    33773377 
    33783378    def checkStartsLowercase(identifier as String, whatName as String) 
     
    33923392                sugg = sugg[0].toString.toLower + sugg[1:] 
    33933393                sugg = ' Try "[sugg]".' 
    33943394            .recordError('[whatName] declarations cannot start with an underscore. Those are reserved for class variables.[sugg]') 
    3395         if Utils.startsNonLower(identifier) 
     3395        if identifier.startsIsNonLower 
    33963396            sugg = identifier[0].toString.toLower + identifier[1:] 
    33973397            .recordError('[whatName] declarations must start with a lowercase letter to distinguish them from other types of identifiers. Try "[sugg]".') 
    33983398 
     
    34133413        """ 
    34143414        token = .peek(peekAhead) 
    34153415        if token.which == 'ID' 
    3416             return Utils.startsNonLower(token.value to String) 
     3416            return (token.value to String).startsIsNonLower 
    34173417        return .isOneOfKeywords(token, ['bool', 'char', 'decimal', 'int', 'uint', 'float', 'number']) 
    34183418 
    34193419    def looksLikeVarNameIsNext(peekAhead as int) as bool 
    34203420        token = .peek(peekAhead) 
    3421         return token is not nil and token.which=='ID' and Utils.startsWithLowerLetter(token.text) 
     3421        return token is not nil and token.which=='ID' and token.text.startsIsLower 
    34223422         
    34233423    def isOneOfKeywords(nToken as IToken?, keywords as List<of String>) as bool 
    34243424        token = nToken to ! 
  • Source/TestifyRunner.cobra

     
    195195                paths.addRange(Directory.getDirectories('.') to passthrough) 
    196196                paths.sort 
    197197                for baseName in paths 
    198                     baseName = Utils.normalizePath(baseName) 
     198                    baseName = Utils.pathNormalizeLeading(baseName) 
    199199                    if baseName.startsWith('_'), continue 
    200200                    if baseName.endsWith('.cobra') or baseName.endsWith('.COBRA') 
    201201                        _testifyCount += .testifyFile(baseName) 
     
    245245        print 
    246246        print 
    247247        print 'RUN [baseName]' 
    248         print '    [Utils.combinePaths(Environment.currentDirectory, baseName)]' 
     248        print '    [Utils.pathCombine(Environment.currentDirectory, baseName)]' 
    249249        print '    Test #[_testifyCount+1]' 
    250250        print bar 
    251251        print bar 
     
    266266                print 'Running multiple files.' 
    267267                for fileName in firstLine.substring(firstLine.indexOf('.multi.')+8).split 
    268268                    if fileName.length 
    269                         fileNames.add(Utils.combinePaths(Path.getDirectoryName(baseName) to !, fileName)) 
    270                 print 'Multiple filenames:', Utils.join(', ', fileNames) 
     269                        fileNames.add(Utils.pathCombine(Path.getDirectoryName(baseName) to !, fileName)) 
     270                print 'Multiple filenames:', ', '.join(fileNames) 
    271271                # enable having another directive on the next line, such as .error. 
    272272                lines = lines[1:] 
    273273                firstLine = lines[0] 
  • Developer/IntermediateReleaseNotes.text

     
    3434 
    3535* Added extension methods to List<of T>. @@ expand on this 
    3636 
     37* Moved useful Utils methods to extension methods.  ticket 111 
     38 
    3739================================================================================ 
    3840Command Line 
    3941================================================================================