def GenerateTags(buff): """Create a DocStruct object that represents a Configuration File @param buff: a file like buffer object (StringIO) """ rtags = taglib.DocStruct() rtags.SetElementDescription('section', "Sections") section = None for lnum, line in enumerate(buff): line = line.strip() # Skip comment and empty lines if line.startswith(u"#") or line.startswith(u";") or not line: continue # Check for a section if line.startswith(u"["): secend = line.find(u"]") if secend != -1: section = taglib.Section(line[1:secend], lnum) rtags.AddElement('section', section) continue # Go to next line # Look for keys if u"=" in line and section is not None: key = taglib.Variable(line.split(u"=")[0], lnum) section.AddElement('key', key) return rtags
def getCFV(self, code_lines): container_list = [] vset = set() for num, line in code_lines: try: # FUNCTION # if parselib.HasToken(line, Token.Keyword, "def"): self.insertFunction(line, num, container_list) # CLASS # elif parselib.HasToken(line, Token.Keyword, "class"): self.insertClass(line, num, container_list) # Global Variable Only # elif parselib.HasToken(line, Token.Operator, "="): vname = parselib.GetTokenValue(line, Token.Name) flevel = self._getLevel(line) if flevel == 0: if not vname in vset: self.rtags.AddVariable(taglib.Variable(vname, num)) vset.add(vname) except parselib.TokenNotFound: pass return self.rtags
def CaptureClassElements(scope, line, idx): """Get recursively capture all the elements defined on the line from the index. @param scope: Scope object to append element to @param line: string of text to parse @param idx: current index in line @return: new index """ idx = parselib.SkipWhitespace(line, idx) dend = line[idx:].find(u"{") + idx if idx >= len(line) or idx == dend: return idx segments = line[idx:dend].strip().split() if len(segments): token = segments[0] idx += len(token) if token.startswith(u'.'): # Descendant class nextscope = taglib.Class(token, scope.GetLine()) scope.AddElement('class', nextscope) # Recurse to look for more children idx = CaptureClassElements(nextscope, line, idx) elif token.startswith(u'#'): # An ID obj = taglib.Variable(token, scope.GetLine()) scope.AddElement('variable', obj) else: # Element p, div, etc.. obj = CSSTag(token, scope.GetLine()) scope.AddElement('tag_red', obj) return idx
def GenerateTags(buff): """Create a DocStruct object that represents a NSIS Script @param buff: a file like buffer object (StringIO) @todo: generate tags for lua tables? """ rtags = taglib.DocStruct() # Set Descriptions of Document Element Types rtags.SetElementDescription('variable', "Defines") rtags.SetElementDescription('section', "Section Definitions") rtags.SetElementDescription('macro', "Macro Definitions") rtags.SetElementDescription('function', "Function Definitions") rtags.SetElementPriority('variable', 4) rtags.SetElementPriority('section', 3) rtags.SetElementPriority('function', 2) rtags.SetElementPriority('macro', 1) # Parse the lines for code objects for lnum, line in enumerate(buff): line = line.strip() llen = len(line) # Skip comment and empty lines if line.startswith(u"#") or line.startswith(u";") or not line: continue # Look for functions and sections if parselib.IsToken(line, 0, u'Function'): parts = line.split() if len(parts) > 1: rtags.AddFunction(taglib.Function(parts[1], lnum)) elif parselib.IsToken(line, 0, u'Section'): parts = line.split() if len(parts) > 1 and parts[1][0] not in ['"', "'", "`"]: rtags.AddElement('section', taglib.Section(parts[1], lnum)) else: for idx, part in enumerate(parts[1:]): if parts[idx][-1] in ['"', "'", "`"]: rtags.AddElement('section', taglib.Section(part, lnum)) break elif parselib.IsToken(line, 0, u'!macro'): parts = line.split() if len(parts) > 1: rtags.AddElement('macro', taglib.Macro(parts[1], lnum)) elif parselib.IsToken(line, 0, u'!define'): parts = line.split() if len(parts) > 1 and parts[1][0].isalpha(): rtags.AddVariable(taglib.Variable(parts[1], lnum)) else: continue return rtags
def action_addVar(self, token, value, num, parms): """ Variable Class, add to rtag, and pop name """ NotUsed(token, value) varid, next_state = parms self.state = next_state fname = self.ids[varid].pop() if (hasattr(self, 'currentclasstag')): self.currentclasstag.AddVariable( taglib.Variable(fname, num, self.currentclasstag.GetName())) return True
def GenerateTags(buff): """Create a DocStruct object that represents an Inno Setup Script @param buff: a file like buffer object (StringIO) @todo: perhaps group functions, procedures within the Scope of a Section object. """ rtags = taglib.DocStruct() rtags.SetElementDescription('section', "Sections") rtags.SetElementDescription('variable', "Defines") rtags.SetElementDescription('function', "Function Definitions") rtags.SetElementDescription('procedure', "Procedure Definitions") rtags.SetElementPriority('section', 3) rtags.SetElementPriority('function', 2) rtags.SetElementPriority('procedure', 1) for lnum, line in enumerate(buff): line = line.strip() # Skip comment and empty lines if line.startswith(u";") or not line: continue # Check for a section if line.startswith(u"["): secend = line.find(u"]") if secend != -1: section = taglib.Section(line[1:secend], lnum) rtags.AddElement('section', section) elif line.startswith(u"function") and \ len(line) > 8 and line[8].isspace(): name = parselib.GetFirstIdentifier(line[8:].strip()) if name is not None: rtags.AddFunction(taglib.Function(name, lnum)) elif line.startswith(u"procedure") and \ len(line) > 9 and line[9].isspace(): name = parselib.GetFirstIdentifier(line[9:].strip()) if name is not None: rtags.AddElement('procedure', taglib.Function(name, lnum, 'procedure')) elif line.startswith(u"#define") and \ len(line) > 7 and line[7].isspace(): name = parselib.GetFirstIdentifier(line[7:].strip()) if name is not None: rtags.AddVariable(taglib.Variable(name, lnum)) else: pass return rtags
def getCFV(self, code_lines): container_list = [] vset = set() for num, line in code_lines: try: if len(line): ltxt = u"".join([l[1].strip() for l in line]) if len(ltxt) and not ltxt.startswith(u"#"): if parselib.BeginsWithAnyOf( line, Token.Keyword, (u"def", u"class", u"if", u"else")): self.pushPopScope(self._getLevel(line)) if len(self._levels) == 1: container_list = [(0, u"", self.rtags)] # FUNCTION # if parselib.HasToken(line, Token.Keyword, "def"): self.insertFunction(line, num, container_list) # CLASS # elif parselib.HasToken(line, Token.Keyword, "class"): self.insertClass(line, num, container_list) # Global Variable Only # elif parselib.HasToken(line, Token.Operator, "="): vname = parselib.GetTokenValue(line, Token.Name) flevel = self._getLevel(line) if flevel == 0: if not vname in vset: self.rtags.AddVariable(taglib.Variable(vname, num)) vset.add(vname) except parselib.TokenNotFound: pass return self.rtags
def GenerateTags(buff): """Create a DocStruct object that represents the list of files in a patch @param buff: a file like buffer object (StringIO) """ rtags = taglib.DocStruct() rtags.SetElementDescription('variable', "Files") # Parse the buffer for lnum, line in enumerate(buff): line = line.strip() if len(line)==0: continue match = RE_FILE.match(line) if match: cname = match.groups()[-1] cobj = taglib.Variable(cname, lnum) rtags.AddVariable(cobj) continue return rtags
def GenerateTags(buff): """Create a DocStruct object that represents a Php Script @param buff: a file like buffer object (StringIO) """ rtags = taglib.DocStruct() # Setup document structure rtags.SetElementDescription('function', "Function Definitions") inphp = False # Are we in a php section or not inclass = False # Inside a class defintion incomment = False # Inside a comment infundef = False # Inside a function definition lastclass = None lastfun = None instring = False openb = 0 # Keep track of open brackets for lnum, line in enumerate(buff): line = line.strip() llen = len(line) idx = 0 while idx < len(line): # Skip Whitespace idx = parselib.SkipWhitespace(line, idx) # Walk through strings ignoring contents if instring or line[idx] in (u"'", u'"'): idx, instring = parselib.FindStringEnd(line[idx:], idx) # For multiline strings if instring: continue # Check if in a <?php ?> block or not if line[idx:].startswith(u'<?'): idx += 2 if line[idx:].startswith(u'php'): idx += 5 inphp = True elif line[idx:].startswith(u'?>'): idx += 2 inphp = False # Skip anything not in side of a php section if not inphp: idx += 1 continue # Check for coments if line[idx:].startswith(u'/*'): idx += 2 incomment = True elif line[idx:].startswith(u'//') or line[idx:].startswith(u'#'): break # go to next line elif line[idx:].startswith(u'*/'): idx += 2 incomment = False # At end of line if idx >= llen: break # Look for tags if incomment: idx += 1 elif line[idx] == u'{': idx += 1 openb += 1 # Class name must be followed by a { if not inclass and lastclass is not None: inclass = True rtags.AddClass(lastclass) elif lastfun is not None: infundef = True lastfun = None else: pass elif line[idx] == u'}': idx += 1 openb -= 1 if inclass and openb == 0: inclass = False lastclass = None elif infundef and inclass and openb == 1: infundef = False elif infundef and openb == 0: infundef = False lastfun = None else: pass elif not infundef and parselib.IsToken(line, idx, u'class'): # Skip whitespace idx = parselib.SkipWhitespace(line, idx + 5) name = parselib.GetFirstIdentifier(line[idx:]) if name is not None: idx += len(name) # Move past the class name lastclass = taglib.Class(name, lnum) elif parselib.IsToken(line, idx, u'function'): # Skip whitespace idx = parselib.SkipWhitespace(line, idx + 8) name = parselib.GetFirstIdentifier(line[idx:]) if name is not None: lastfun = name # Skip whitespace idx = parselib.SkipWhitespace(line, idx + len(name)) if line[idx] != u'(': continue if inclass and lastclass is not None: lastclass.AddMethod(taglib.Method(name, lnum, lastclass.GetName())) else: rtags.AddFunction(taglib.Function(name, lnum)) elif inclass and parselib.IsToken(line, idx, u'var'): # Look for class variables idx += 3 parts = line[idx:].split() if len(parts) and parts[0].startswith(u'$'): name = parselib.GetFirstIdentifier(parts[0][1:]) if name is not None and lastclass is not None: name = u'$' + name lastclass.AddVariable(taglib.Variable(name, lnum, lastclass.GetName())) idx += len(name) else: idx += 1 return rtags
def GenerateTags(buff): """Create a DocStruct object that represents a Tcl Script @param buff: a file like buffer object (StringIO) """ rtags = taglib.DocStruct() rtags.SetElementDescription('procedure', "Procedure Definitions") rtags.SetElementDescription('class', "SNIT") # Scope tracking for SNIT blocks insnit = False cursnit = None openparens = 0 for lnum, line in enumerate(buff): line = line.strip() # Skip comment and empty lines if line.startswith(u"#") or not line: continue if insnit and cursnit is not None: if parselib.IsToken(line, 0, u'method') or \ parselib.IsToken(line, 0, u'typemethod'): parts = line.split() if len(parts) > 1: name = parts[1] cursnit.AddMethod(taglib.Method(name, lnum)) elif parselib.IsToken(line, 0, u'typevariable') or \ parselib.IsToken(line, 0, u'variable'): parts = line.split() if len(parts) > 1: name = parts[1] cursnit.AddVariable(taglib.Variable(name, lnum)) elif parselib.IsToken(u'constructor', 0, line) or \ parselib.IsToken(u'destructor', 0, line): name = parselib.GetFirstIdentifier(line) cursnit.AddMethod(taglib.Method(name, lnum)) elif parselib.IsToken(line, 0, u"package"): pkg = GetPackage(line, lnum) if pkg: cursnit.AddElement('package', pkg) # Update Scope openparens += GetParenCount(line) if openparens == 0: insnit = False cursnit = None continue # Check for Procedure defs if parselib.IsToken(line, 0, u'proc'): parts = line.split() if len(parts) > 1: name = parts[1] if u"::" in name: spaces = name.split("::") space_l = rtags.GetElement('namespace', spaces[0]) if space_l == None: space_l = taglib.Namespace(spaces[0], lnum) rtags.AddElement('namespace', space_l) space_l.AddElement('procedure', taglib.Procedure(spaces[-1], lnum)) else: rtags.AddElement('procedure', taglib.Procedure(parts[1], lnum)) elif line.startswith(u'snit::'): parts = line.split() if len(parts) > 1: insnit = True openparens = GetParenCount(line) name = parts[1] cursnit = taglib.Class(name, lnum) rtags.AddClass(cursnit) elif parselib.IsToken(line, 0, u"package"): pkg = GetPackage(line, lnum) if pkg: rtags.AddElement('package', pkg) return rtags
def GenerateTags(buff): """Create a DocStruct object that represents the structure of a Java source file. @param buff: a file like buffer object (StringIO) """ rtags = taglib.DocStruct() rtags.SetElementDescription('class', "<no package>") rtags.SetElementDescription('variable', "Imports") # State Variables inComment = False currentLevel = 0 methodSignature = None methodLnum = 0 methodClass = None lastClass = [] imports = None # Parse the buffer # Simple line based parser, likely not to be accurate in all cases for lnum, line in enumerate(buff): lastLevel = currentLevel lineCodeOnly = line[:] lineCodeOnly = RE_BACKSLASHEDQUOTE_INLINE.sub("'",lineCodeOnly) lineCodeOnly = RE_STRING_INLINE.sub('',lineCodeOnly) lineCodeOnly = RE_CHARACTER_INLINE.sub('',lineCodeOnly) #print "[[[",lineCodeOnly,"]]]" # remove trailing comments cut = line.find('//') if cut>-1: line = line[:cut] line = RE_COMMENT_INLINE.sub('',line) if inComment: cut = line.find('*/') if cut>-1: line = line[cut+2:] inComment = False else: continue # remove starting comments cut = line.find('/*') if cut>-1: line = line[:cut] inComment = True line = line.strip() if len(line)==0: continue diff = lineCodeOnly.count('{') - lineCodeOnly.count('}') currentLevel += diff print "<<<",line,">>>", lnum, currentLevel, diff, len(lastClass), inComment if diff < 0: while len(lastClass) > currentLevel: #print "POP", len(lastClass), currentLevel, lastClass[-1] lastClass.pop() # handle multi-line method definition if methodSignature: cl = line.find(')') if cl > -1: if cl==0: methodSignature += ')' else: methodSignature += ' ' + line[:cl] methodClass.AddMethod(taglib.Method(methodSignature, methodLnum)) #print "METH == ", methodSignature methodSignature = None continue else: methodSignature += ' ' + line #print "METH ++ ", methodSignature continue if currentLevel == 0: match = RE_PACKAGE.match(line) if match: groups = match.groups() #print "PACKAGE", groups rtags.SetElementDescription('class', groups[-1]) continue match = RE_IMPORT.match(line) if match: groups = match.groups() #print "IMPORT", groups cobj = taglib.Variable(groups[-1], lnum) rtags.AddVariable(cobj) continue match = RE_CLASS.match(line) if match: cname = match.groups()[-1] if len(lastClass) > 0: cname = '$ '+cname cobj = taglib.Class(cname, lnum) rtags.AddClass(cobj) lastClass.append(cobj) #print "CLASS", cname continue if len(lastClass) == lastLevel: match = RE_METH.match(line) if match: groups = match.groups() prefix = '' methodSignature = groups[-2] warning = None if groups[3] == None: contructor_for = lastClass[-1].GetName() if contructor_for[0] == '$': contructor_for = contructor_for[2:] if groups[-2] == contructor_for: prefix = '>' else: warning = 'tag_red' methodSignature += ' - ???' else: methodSignature += ' - ' + groups[3] methodSignature += ' (' if groups[1] and (groups[1].find('static') > -1): prefix += '_' if groups[2] and (groups[2].find('abstract') > -1): prefix += '@' if len(prefix) > 0: methodSignature = prefix + ' ' + methodSignature if groups[-1]: methodSignature += groups[-1] if line.find(')') > -1: methodSignature += ')' cobj = taglib.Method(methodSignature, lnum) if warning: cobj.type = warning lastClass[-1].AddMethod(cobj) #print "METH", groups, methodSignature, lastClass[-1] methodSignature = None else: methodLnum = lnum methodClass = lastClass[-1] continue match = RE_CONST.match(line) if match: groups = match.groups() #print "CONST", groups, lastClass[-1] cname = groups[-1] + ' -- ' + groups[-2] cobj = taglib.Macro(cname, lnum) lastClass[-1].AddVariable(cobj) continue match = RE_VAR.match(line) if match: groups = match.groups() #print "VAR", groups, lastClass[-1] cname = groups[-1] + ' - ' + groups[-2] #print groups[-2] if groups[-2][:6]=='throws': continue if groups[1] and (groups[1].find('static') > -1): cname = '_ ' + cname cobj = taglib.Variable(cname, lnum) lastClass[-1].AddVariable(cobj) continue return rtags
def GenerateTags(buff): """Create a DocStruct object that represents a Php Script @param buff: a file like buffer object (StringIO) """ rtags = taglib.DocStruct() # Setup document structure rtags.SetElementDescription('function', "Function Definitions") inphp = False # Are we in a php section or not inclass = False # Inside a class defintion incomment = False # Inside a comment infundef = False # Inside a style definition {} lastclass = None lastfun = None openb = 0 # Keep track of open brackets for lnum, line in enumerate(buff): line = line.strip() llen = len(line) idx = 0 while idx < len(line): # Skip Whitespace idx += (len(line[idx:]) - len(line[idx:].lstrip())) # Check if in a <?php ?> block or not if line[idx:].startswith(u'<?php'): idx += 5 inphp = True elif line[idx:].startswith(u'?>'): idx += 2 inphp = False # Skip anything not in side of a php section if not inphp: idx += 1 continue # Check for coments if line[idx:].startswith(u'/*'): idx += 2 incomment = True elif line[idx:].startswith(u'//') or line[idx:].startswith(u'#'): break # go to next line elif line[idx:].startswith(u'*/'): idx += 2 incomment = False # At end of line if idx >= llen: break # Look for tags if incomment: idx += 1 elif line[idx] in u'{': idx += 1 openb += 1 # Class name must be followed by a { if not inclass and lastclass is not None: inclass = True rtags.AddClass(lastclass) elif lastfun is not None: infundef = True lastfun = None else: pass elif line[idx] == u'}': idx += 1 openb -= 1 if inclass and openb == 0: inclass = False lastclass = None elif infundef and inclass and openb == 1: infundef = False elif infundef and openb == 0: infundef = False lastfun = None else: pass elif not infundef and line[idx:].startswith(u'class') \ and llen > idx + 5 and line[idx+5].isspace(): idx += 5 # Skip whitespace idx += (len(line[idx:]) - len(line[idx:].lstrip())) name = parselib.GetFirstIdentifier(line[idx:]) if name is not None: idx += len(name) # Move past the class name lastclass = taglib.Class(name, lnum) else: # Something must be wrong so skip ahead and keep going idx += 5 elif line[idx:].startswith( u'function') and llen > idx + 8 and line[idx + 8].isspace(): idx += 8 # Skip whitespace idx += (len(line[idx:]) - len(line[idx:].lstrip())) name = parselib.GetFirstIdentifier(line[idx:]) if name is not None: lastfun = name idx += len(name) # Skip whitespace idx += (len(line[idx:]) - len(line[idx:].lstrip())) if line[idx] != u'(': continue if inclass and lastclass is not None: lastclass.AddMethod( taglib.Method(name, lnum, lastclass.GetName())) else: rtags.AddFunction(taglib.Function(name, lnum)) elif inclass and line[idx:].startswith(u'var') \ and llen > idx + 3 and line[idx+3].isspace(): # Look for class variables idx += 3 parts = line[idx:].split() if len(parts) and parts[0].startswith(u'$'): name = parselib.GetFirstIdentifier(parts[0][1:]) if name is not None and lastclass is not None: name = u'$' + name lastclass.AddVariable( taglib.Variable(name, lnum, lastclass.GetName())) idx += len(name) elif line[idx] == u'=' and llen > idx + 1 and line[idx + 1] != u'=': break # jump to next line when we find an assigment else: idx += 1 return rtags
def GenerateTags(buff): """Create a DocStruct object that represents a haXe Script @param buff: a file like buffer object (StringIO) """ rtags = taglib.DocStruct() # Setup document structure rtags.SetElementDescription('class', "Class Definitions") rtags.SetElementDescription('function', "Function Definitions") inclass = False # Inside a class defintion incomment = False # Inside a comment infundef = False # Inside a function definition lastclass = None lastfun = None openb = 0 # Keep track of open brackets for lnum, line in enumerate(buff): line = line.strip() llen = len(line) idx = 0 while idx < len(line): # Skip Whitespace idx = parselib.SkipWhitespace(line, idx) # Check for coments if line[idx:].startswith(u'/*'): idx += 2 incomment = True elif line[idx:].startswith(u'//'): break # go to next line elif line[idx:].startswith(u'*/'): idx += 2 incomment = False # At end of line if idx >= llen: break # Look for tags if incomment: idx += 1 elif line[idx] == u'{': idx += 1 openb += 1 # Class name must be followed by a { if not inclass and lastclass is not None: inclass = True rtags.AddClass(lastclass) elif lastfun is not None: infundef = True lastfun = None else: pass elif line[idx] == u'}': idx += 1 openb -= 1 if inclass and openb == 0: inclass = False lastclass = None elif infundef and inclass and openb == 1: infundef = False elif infundef and openb == 0: infundef = False lastfun = None else: pass elif not infundef and parselib.IsToken(line, idx, u'class'): # Skip whitespace idx = parselib.SkipWhitespace(line, idx + 5) name = parselib.GetFirstIdentifier(line[idx:]) if name is not None: idx += len(name) # Move past the class name lastclass = taglib.Class(name, lnum) elif parselib.IsToken(line, idx, u'function'): # Skip whitespace idx = parselib.SkipWhitespace(line, idx + 8) name = parselib.GetFirstIdentifier(line[idx:]) if name is not None: lastfun = name # Skip whitespace idx = parselib.SkipWhitespace(line, idx + len(name)) if line[idx] != u'(': continue if inclass and lastclass is not None: lastclass.AddMethod( taglib.Method(name, lnum, lastclass.GetName())) else: rtags.AddFunction(taglib.Function(name, lnum)) elif inclass and not infundef and parselib.IsToken( line, idx, u'var'): # Look for class variables idx = parselib.SkipWhitespace(line, idx + 3) name = parselib.GetFirstIdentifier(line[idx:]) if name is not None and lastclass is not None: lastclass.AddVariable( taglib.Variable(name, lnum, lastclass.GetName())) idx += len(name) else: idx += 1 return rtags
def GenerateTags(buff): """Create a DocStruct object that represents a Cascading Style Sheets @param buff: a file like buffer object (StringIO) @todo: add support for parsing selectors and grouping classes and identities of each selector in a subscope. """ rtags = taglib.DocStruct() # Setup document structure # rtags.SetElementDescription('tag', "Selectors") # Use variables node for global identities rtags.SetElementDescription('variable', "Identities") # Use classes for global classes # Uses DocStruct builtin c_tag = None # Currenly found tag incomment = False # Inside a comment indef = False # Inside a style definition {} for lnum, line in enumerate(buff): line = line.strip() llen = len(line) idx = 0 while idx < len(line): # Skip Whitespace while line[idx].isspace(): idx += 1 # Check if valid item to add to document # if c_tag is not None and line[idx] == u'{': # rtags.AddElement('tag', c_tag) # c_tag = None # Check for coments if line[idx] == u'/' and llen > idx and line[idx + 1] == u'*': idx += 2 incomment = True elif line[idx] == u'*' and llen > idx and line[idx + 1] == u'/': idx += 2 incomment = False # At end of line if idx >= llen: break # Look for tags if incomment: idx += 1 elif line[idx] == u'{': idx += 1 indef = True elif indef and line[idx] == u'}': idx += 1 indef = False elif not indef and line[idx] in (u'.', u'#'): if idx == 0 or line[idx - 1].isspace(): name = parselib.GetFirstIdentifier(line[idx + 1:]) if name is not None: name = line[idx] + name if line[idx] == u'.': rtags.AddClass(taglib.Class(name, lnum)) else: rtags.AddVariable(taglib.Variable(name, lnum)) idx += 1 else: idx += 1 return rtags
def GenerateTags(buff): """Create a DocStruct object that represents a Python file @param buff: a file like buffer object (StringIO) """ rtags = taglib.DocStruct() rtags.SetElementDescription('function', "Function Definitions") rtags.SetElementDescription('class', "Class Definitions") # Variables for managing the state of the parse parents = list() indent = 0 fn_indent = 0 parens = 0 # Paren nesting count indocstring = False ind_string = False # Double quote string ins_string = False # Single quote string infunction = False lastclass = None def NotInString(): """Return whether the current state of the parse is in a string or not. """ return not indocstring and not ind_string and not ins_string # Do the parse of the text for lnum, line in enumerate(buff): indent = 0 idx = 0 llen = len(line) while idx < llen: # Check for docstrings if not (ind_string or ins_string) and llen >= idx + 3 and line[idx:idx + 3] in [ '"""', "'''" ]: indocstring = not indocstring idx += 3 continue # If end of line or start of comment start next line if idx == llen or (line[idx] == u"#" and NotInString()): break # Check indent sensitive tokens if not indocstring and not line[idx].isspace(): if infunction and indent < fn_indent: infunction = False if lastclass is not None: if indent <= lastclass.get('indent', 0): parents = PopScopes(parents, indent) if len(parents): lastclass = parents[-1] else: lastclass = None # Check for if in a string or not if line[idx] == u"'" and not ind_string and \ idx > 0 and line[idx-1] != "\\": # Single string ins_string = not ins_string idx += 1 elif line[idx] == u'"' and not ins_string and \ idx > 0 and line[idx-1] != "\\": # Double String ind_string = not ind_string idx += 1 else: pass # Parse and look for elements to add to the DocStruct if not NotInString(): # Token is in a string so ignore and move on idx = idx + 1 elif line[idx].isspace(): # Get indent width for current scope if idx == 0: indent = (len(line) - len(line.lstrip())) idx += indent else: # Non indent space idx += 1 elif parselib.IsToken(line, idx, u'class'): idx += 5 cname = parselib.GetFirstIdentifier(line[idx:]) if cname is not None: if lastclass is None: rtags.AddClass(taglib.Class(cname, lnum)) # TODO: check for classes defined within classes lastclass = dict(name=cname, indent=indent) parents.append(dict(lastclass)) break # Go to next line elif parselib.IsToken(line, idx, u'def'): # Function/Method Definition idx += 3 fname = parselib.GetFirstIdentifier(line[idx:]) if line[idx].isspace() and fname is not None: infunction = True fn_indent = indent + 1 if not line[0].isspace() or lastclass is None or \ not len(lastclass.get("name", "")): rtags.AddFunction(taglib.Function(fname, lnum)) else: lclass = rtags.GetLastClass() if lclass is not None: lclass.AddMethod( taglib.Method(fname, lnum, lclass.GetName())) else: # Something must have failed with the parse so # ignore this element. pass break elif not infunction and line[idx] in u"()": # Track paren nesting to help with variable parsing if line[idx] == u"(": parens += 1 else: parens -= 1 idx += 1 elif not infunction and line[idx] == u"=" and not parens: # Check for Global and Class variables idx += 1 if line[idx] != u"=": # ignore == statements var = line[:idx - 1].strip().split() if len(var) == 1 and parselib.IsGoodName(var[0]): lclass = rtags.GetLastClass() # Check if we are still inside a class def or not if lastclass is not None and lclass is not None: vobj = taglib.Variable(var[0], lnum, lclass.GetName()) lclass.AddVariable(vobj) else: # Global Scope variable rtags.AddVariable(taglib.Variable(var[0], lnum)) else: # Nothing so skip ahead idx += 1 # Return the document structure object return rtags
def GenerateTags(buff): """Create a DocStruct object that represents a Cascading Style Sheets @param buff: a file like buffer object (StringIO) @todo: add support for parsing selectors and grouping classes and identities of each selector in a subscope. """ rtags = taglib.DocStruct() # Setup document structure # Use variables node for global identities rtags.SetElementDescription('variable', "Identities") rtags.SetElementDescription('tag_red', "Elements") # Use classes for global classes # Uses DocStruct builtin c_tag = None # Currently found tag incomment = False # Inside a comment indef = False # Inside a style definition {} for lnum, line in enumerate(buff): line = line.strip() llen = len(line) idx = 0 while idx < len(line): idx = parselib.SkipWhitespace(line, idx) # Check for comments if llen > idx + 1 and line[idx] == u'/' and line[idx + 1] == u'*': idx += 2 incomment = True elif llen > idx + 1 and line[idx] == u'*' and line[idx + 1] == u'/': idx += 2 incomment = False # At end of line if idx >= llen: break # Look for tags if incomment: idx += 1 elif line[idx] == u'{': idx += 1 indef = True elif indef and line[idx] == u'}': idx += 1 indef = False elif not indef and line[idx] in (u'.', u'#'): # Classes and ID's if idx == 0 or line[idx - 1].isspace(): names = line[idx:].split() if len(names): name = names[0] else: name = None if name is not None: if line[idx] == u'.': # See if we already have found previous # defs using this class identifier cobj = rtags.GetElement('class', name) if cobj is None: cobj = taglib.Class(name, lnum) rtags.AddClass(cobj) # Update the index idx += len(name) # Grab all other defs that may be children of # the current one. idx = CaptureClassElements(cobj, line, idx) else: # Stand alone ID rtags.AddVariable(taglib.Variable(name, lnum)) idx += len(name) continue # TODO: smarter skip ahead to speed up parse idx += 1 elif not indef and not line[idx].isspace(): # Possible element nparen = line[idx:].find(u'{') + idx token = line[idx:nparen] if token: idx += len(token) if not token.startswith(u"@"): obj = CSSTag(token.strip(), lnum) rtags.AddElement('tag_red', obj) else: idx += 1 else: # TODO: smarter skip ahead to speed up parse idx += 1 return rtags