ThirdParty/Jasy/jasy/js/api/Comment.py

branch
maintenance
changeset 6693
3629d88ae235
parent 6647
2a11e1b2dcbe
parent 6692
c104c120e043
child 6694
1cccd74fd355
equal deleted inserted replaced
6647:2a11e1b2dcbe 6693:3629d88ae235
1 #
2 # Jasy - Web Tooling Framework
3 # Copyright 2010-2012 Zynga Inc.
4 #
5
6 from __future__ import unicode_literals
7
8 import re
9
10 import jasy.core.Console as Console
11
12 __all__ = ["CommentException", "Comment"]
13
14
15 # Used to measure the doc indent size (with leading stars in front of content)
16 docIndentReg = re.compile(r"^(\s*\*\s*)(\S*)")
17
18
19 class CommentException(Exception):
20 """
21 Thrown when errors during comment processing are detected.
22 """
23 def __init__(self, message, lineNo=0):
24 Exception.__init__(self, "Comment error: %s (line: %s)" % (message, lineNo+1))
25
26
27 class Comment():
28 """
29 Comment class is attached to parsed nodes and used to store all comment related
30 information.
31
32 The class supports a new Markdown and TomDoc inspired dialect to make developers life
33 easier and work less repeative.
34 """
35
36 # Relation to code
37 context = None
38
39 # Collected text of the comment
40 text = None
41
42 def __init__(self, text, context=None, lineNo=0, indent="", fileId=None):
43
44 # Store context (relation to code)
45 self.context = context
46
47 # Store fileId
48 self.fileId = fileId
49
50 # Figure out the type of the comment based on the starting characters
51
52 # Inline comments
53 if text.startswith("//"):
54 # "// hello" => " hello"
55 text = " " + text[2:]
56 self.variant = "single"
57
58 # Doc comments
59 elif text.startswith("/**"):
60 # "/** hello */" => " hello "
61 text = " " + text[3:-2]
62 self.variant = "doc"
63
64 # Protected comments which should not be removed
65 # (e.g these are used for license blocks)
66 elif text.startswith("/*!"):
67 # "/*! hello */" => " hello "
68 text = " " + text[3:-2]
69 self.variant = "protected"
70
71 # A normal multiline comment
72 elif text.startswith("/*"):
73 # "/* hello */" => " hello "
74 text = " " + text[2:-2]
75 self.variant = "multi"
76
77 else:
78 raise CommentException("Invalid comment text: %s" % text, lineNo)
79
80 # Multi line comments need to have their indentation removed
81 if "\n" in text:
82 text = self.__outdent(text, indent, lineNo)
83
84 # For single line comments strip the surrounding whitespace
85 else:
86 # " hello " => "hello"
87 text = text.strip()
88
89 # The text of the comment
90 self.text = text
91
92 def __outdent(self, text, indent, startLineNo):
93 """
94 Outdent multi line comment text and filtering empty lines
95 """
96
97 lines = []
98
99 # First, split up the comments lines and remove the leading indentation
100 for lineNo, line in enumerate((indent+text).split("\n")):
101
102 if line.startswith(indent):
103 lines.append(line[len(indent):].rstrip())
104
105 elif line.strip() == "":
106 lines.append("")
107
108 else:
109 # Only warn for doc comments, otherwise it might just be code commented
110 # out which is sometimes formatted pretty crazy when commented out
111 if self.variant == "doc":
112 Console.warn("Could not outdent doc comment at line %s in %s",
113 startLineNo+lineNo, self.fileId)
114
115 return text
116
117 # Find first line with real content, then grab the one after it to get the
118 # characters which need
119 outdentString = ""
120 for lineNo, line in enumerate(lines):
121
122 if line != "" and line.strip() != "":
123 matchedDocIndent = docIndentReg.match(line)
124
125 if not matchedDocIndent:
126 # As soon as we find a non doc indent like line we stop
127 break
128
129 elif matchedDocIndent.group(2) != "":
130 # otherwise we look for content behind the indent to get the
131 # correct real indent (with spaces)
132 outdentString = matchedDocIndent.group(1)
133 break
134
135 lineNo += 1
136
137 # Process outdenting to all lines (remove the outdentString from the start
138 # of the lines)
139 if outdentString != "":
140
141 lineNo = 0
142 outdentStringLen = len(outdentString)
143
144 for lineNo, line in enumerate(lines):
145 if len(line) <= outdentStringLen:
146 lines[lineNo] = ""
147
148 else:
149 if not line.startswith(outdentString):
150
151 # Only warn for doc comments, otherwise it might just be code
152 # commented out which is sometimes formatted pretty crazy when
153 # commented out
154 if self.variant == "doc":
155 Console.warn(
156 "Invalid indentation in doc comment at line %s in %s",
157 startLineNo+lineNo, self.fileId)
158
159 else:
160 lines[lineNo] = line[outdentStringLen:]
161
162 # Merge final lines and remove leading and trailing new lines
163 return "\n".join(lines).strip("\n")

eric ide

mercurial