Coverage for C:\Repos\leo-editor\leo\plugins\importers\java.py: 88%

101 statements  

« prev     ^ index     » next       coverage.py v6.4, created at 2022-05-24 10:21 -0500

1#@+leo-ver=5-thin 

2#@+node:ekr.20140723122936.18143: * @file ../plugins/importers/java.py 

3"""The @auto importer for the java language.""" 

4import re 

5from leo.core import leoGlobals as g 

6from leo.plugins.importers import linescanner 

7assert g 

8Importer = linescanner.Importer 

9Target = linescanner.Target 

10#@+others 

11#@+node:ekr.20161126161824.2: ** class Java_Importer 

12class Java_Importer(Importer): 

13 """The importer for the java lanuage.""" 

14 

15 def __init__(self, importCommands, **kwargs): 

16 """Java_Importer.__init__""" 

17 super().__init__( 

18 importCommands, 

19 language='java', 

20 state_class=Java_ScanState, 

21 strict=False, 

22 ) 

23 

24 # Used in multiple methods. 

25 java_keywords = ( 

26 '(break|case|catch|continue|default|do|else|enum|' + 

27 'finally|for|goto|if|new|return|' + 

28 'sizeof|strictfp|struct|super|switch|this|throw|throws|try|while)' 

29 ) 

30 java_types_list = ( 

31 '(abstract|boolean|byte|char|const|double|extends|final|float|int|' + 

32 'interface|long|native|package|private|protected|public|' + 

33 'short|static|transient|void|volatile)' 

34 ) 

35 # 'signed|typedef|union|unsigned)' 

36 java_types_pattern = re.compile(java_types_list) 

37 java_keywords_pattern = re.compile(java_keywords) 

38 

39 #@+others 

40 #@+node:ekr.20161126163014.1: *3* java_i.clean_headline 

41 def clean_headline(self, s, p=None): 

42 """Return the cleaned headline.""" 

43 return s.strip('{').strip() if s.strip().endswith('{') else s.strip() 

44 #@+node:ekr.20161205042019.2: *3* java_i.match_name_patterns 

45 java_name_pattern = re.compile(r'\s*([\w:]+)') 

46 

47 def match_name_patterns(self, line): 

48 """Set self.headline if the line defines a typedef name.""" 

49 m = self.java_name_pattern.match(line) 

50 if m: 

51 word = m.group(1) 

52 if not self.java_types_pattern.match(word): 

53 self.headline = word 

54 #@+node:ekr.20161205042019.3: *3* java_i.match_start_patterns 

55 # Define patterns that can start a block 

56 java_class_pattern = re.compile(r'\s*(%s\s*)*\s*class\s+(\w+)' % (java_types_list)) 

57 java_func_pattern = re.compile(r'\s*(%s\s*)+\s*([\w:]+)' % (java_types_list)) 

58 

59 def match_start_patterns(self, line): 

60 """ 

61 True if line matches any block-starting pattern. 

62 If true, set self.headline. 

63 """ 

64 m = self.java_class_pattern.match(line) 

65 if m: 

66 self.headline = line 

67 return True 

68 m = self.java_func_pattern.match(line) 

69 if m: 

70 i = line.find('(') 

71 self.headline = line[:i] if i > -1 else line 

72 return True 

73 return False 

74 #@+node:ekr.20161205042019.4: *3* java_i.start_new_block 

75 def start_new_block(self, i, lines, new_state, prev_state, stack): 

76 """Create a child node and update the stack.""" 

77 line = lines[i] 

78 target = stack[-1] 

79 # Insert the reference in *this* node. 

80 h = self.gen_ref(line, target.p, target) 

81 # Create a new child and associated target. 

82 if self.headline: 

83 h = self.headline 

84 if new_state.level() > prev_state.level(): 

85 child = self.create_child_node(target.p, line, h) 

86 else: 

87 # We may not have seen the { yet, so adjust. 

88 # Without this, the new block becomes a child of the preceding. 

89 new_state = Java_ScanState() 

90 new_state.curlies = prev_state.curlies + 1 

91 child = self.create_child_node(target.p, line, h) 

92 stack.append(Target(child, new_state)) 

93 # Add all additional lines of the signature. 

94 skip = self.skip # Don't change the ivar! 

95 while skip > 0: 

96 skip -= 1 

97 i += 1 

98 assert i < len(lines), (i, len(lines)) 

99 line = lines[i] 

100 if not self.headline: 

101 self.match_name_patterns(line) 

102 if self.headline: 

103 child.h = '%s %s' % (child.h.strip(), self.headline) 

104 self.add_line(child, lines[i]) 

105 #@+node:ekr.20161205042019.5: *3* java_i.starts_block 

106 def starts_block(self, i, lines, new_state, prev_state): 

107 """True if the new state starts a block.""" 

108 self.headline = None 

109 line = lines[i] 

110 if prev_state.context: 

111 return False 

112 if self.java_keywords_pattern.match(line): 

113 return False 

114 if not self.match_start_patterns(line): 

115 return False 

116 # Must not be a complete statement. 

117 if line.find(';') > -1: 

118 return False 

119 # Scan ahead until an open { is seen. the skip count. 

120 self.skip = 0 

121 while self.skip < 10: 

122 if new_state.level() > prev_state.level(): 

123 return True 

124 self.skip += 1 

125 i += 1 

126 if i < len(lines): 

127 line = lines[i] 

128 prev_state = new_state 

129 new_state = self.scan_line(line, prev_state) 

130 else: 

131 break 

132 return False 

133 #@-others 

134#@+node:ekr.20161126161824.6: ** class class Java_ScanState 

135class Java_ScanState: 

136 """A class representing the state of the java line-oriented scan.""" 

137 

138 def __init__(self, d=None): 

139 """Java_ScanState.__init__""" 

140 if d: 

141 prev = d.get('prev') 

142 self.context = prev.context 

143 self.curlies = prev.curlies 

144 else: 

145 self.context = '' 

146 self.curlies = 0 

147 

148 def __repr__(self): 

149 """Java_ScanState.__repr__""" 

150 return "Java_ScanState context: %r curlies: %s" % ( 

151 self.context, self.curlies) 

152 

153 __str__ = __repr__ 

154 

155 #@+others 

156 #@+node:ekr.20161126161824.7: *3* java_state.level 

157 def level(self): 

158 """Java_ScanState.level.""" 

159 return self.curlies 

160 

161 #@+node:ekr.20161126161824.8: *3* java_state.update 

162 def update(self, data): 

163 """ 

164 Java_ScanState.update 

165 

166 Update the state using the 6-tuple returned by i.scan_line. 

167 Return i = data[1] 

168 """ 

169 context, i, delta_c, delta_p, delta_s, bs_nl = data 

170 # All ScanState classes must have a context ivar. 

171 self.context = context 

172 self.curlies += delta_c 

173 return i 

174 #@-others 

175#@-others 

176importer_dict = { 

177 'func': Java_Importer.do_import(), 

178 'extensions': ['.java'], 

179} 

180#@@language python 

181#@@tabwidth -4 

182#@-leo