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

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

eric ide

mercurial