Skip to content

Commit

Permalink
java switch parsing fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
amiraliakbari committed Dec 28, 2013
1 parent dbde726 commit 4d5c731
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 13 deletions.
13 changes: 12 additions & 1 deletion inspector/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -885,12 +885,15 @@ def __init__(self, condition):
self.default = CodeBlock()
self.active_cases = []

def __unicode__(self):
return u'SwitchBlock: {0} cases'.format(len(self.cases))

def add_case(self, case_expr):
self.active_cases.append(case_expr)
self.case_orders.append(case_expr)

def add_break(self):
self.active_cases = []
self.mode = 'break'

def add_return(self):
self.mode = 'return'
Expand All @@ -899,6 +902,11 @@ def add_default(self):
self.active_cases = 'default'

def add_statement(self, statement):
if statement and isinstance(statement, Statement) and statement.code:
if re.match(r'^break\s*;$', statement.code.strip()):
self.mode = 'break'
if re.match(r'^return\b.*;$', statement.code.strip(), re.DOTALL):
self.mode = 'return'
if not self.active_cases and not self.mode:
raise ValueError('Statement not in a case: {0}.'.format(unicode(statement)))
if self.active_cases == 'default':
Expand All @@ -911,6 +919,9 @@ def add_statement(self, statement):
if self.mode == 'return':
self.mode = ''
self.active_cases = []
if self.mode == 'break':
self.mode = ''
self.active_cases = []


class ExceptionBlock(CodeBlock):
Expand Down
28 changes: 16 additions & 12 deletions inspector/models/java.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ def next_token(self):
t.content = self.read(cond=IsNotBreaking())
# gathering some more data for error reporting, just in case
l2 = self._cur_line
logger.debug('='*40)
logger.debug('CONTENT:'+t.content if t.content is not None else '<NONE>')

# finding parent blocks #
Expand All @@ -164,6 +165,12 @@ def next_token(self):
self.sw = self.find_context_top(lambda x: x.isinstance(SwitchBlock))

ch = self.next_char()
if self.sw:
logger.debug('IN a switch: %s', self.sw)
m1 = re.match(r'^case\s+(?P<cond>.+?)\s*:', t.content)
m2 = re.match(r'^default\s*:', t.content)
if m1 or m2:
ch = ';' # it is a goto! i.e. goto Switch Case handling code

# End-Control Token #
if ch == '}':
Expand Down Expand Up @@ -291,13 +298,13 @@ def next_token(self):
t.content += ';'

if self.statement_pre_read is not None:
ch = self.current_head()
if ch > self.statement_pre_read + 1:
current_head = self.current_head()
if current_head > self.statement_pre_read + 1:
raise AssertionError('bad pre-read! pre-read: {0}, current: {1}'.format(self.statement_pre_read,
ch))
current_head))
else:
logger.info('Statement already read, skipping: %s', t.content)
if self.statement_pre_read == ch - 1:
if self.statement_pre_read == current_head - 1:
self.statement_pre_read = None
else:
is_special_statement = False
Expand All @@ -307,24 +314,21 @@ def next_token(self):

# case
if self.sw:
logger.warning(t.content)
logger.debug("IN SWITCH: %s", t.content)

m = re.match(r'^case\s+(?P<cond>.+?)\s*:', t.content)
if m:
logger.debug('OPENDED case: %s', m.group('cond'))
self.sw.model.add_case(m.group('cond'))
logger.debug('SWITCH is: %s', self.sw)
t = None

elif re.match(r'^default\s*:', t.content):
logger.debug('SWITCH default')
self.sw.model.add_default()
logger.debug('SWITCH is: %s', self.sw)
t = None

elif re.match(r'^break\s*;$', t.content):
self.sw.model.add_break()
t = None

# elif re.match(r'\breturn\b.*;', t.content, re.DOTALL):
# self.sw.model.add_return()

if t is None:
self.rewind_to(first_head)
self.read(find=':', beyond=1)
Expand Down
45 changes: 45 additions & 0 deletions inspector/test/data/java/sample_sources/8.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import static com.github.mobile.RequestCodes.COMMENT_CREATE;
import static com.github.mobile.RequestCodes.ISSUE_ASSIGNEE_UPDATE;
import static com.github.mobile.RequestCodes.ISSUE_CLOSE;
import static com.github.mobile.RequestCodes.ISSUE_EDIT;
import static com.github.mobile.RequestCodes.ISSUE_LABELS_UPDATE;
import static com.github.mobile.RequestCodes.ISSUE_MILESTONE_UPDATE;
import static com.github.mobile.RequestCodes.ISSUE_REOPEN;

import android.os.Bundle;

class SwitchClass1 {
private EditMilestoneTask milestoneTask;
private EditAssigneeTask assigneeTask;
private EditLabelsTask labelsTask;
private EditStateTask stateTask;

public void onDialogResult(int requestCode, int resultCode, Bundle arguments) {
if (RESULT_OK != resultCode)
return;

switch (requestCode) {
case ISSUE_MILESTONE_UPDATE:
milestoneTask.edit(MilestoneDialogFragment.getSelected(arguments));
break;
case ISSUE_ASSIGNEE_UPDATE:
assigneeTask.edit(AssigneeDialogFragment.getSelected(arguments));
break;
case ISSUE_LABELS_UPDATE:
ArrayList<Label> labels = LabelsDialogFragment
.getSelected(arguments);
if (labels != null && !labels.isEmpty())
labelsTask.edit(labels.toArray(new Label[labels.size()]));
else
labelsTask.edit(null);
break;
case ISSUE_CLOSE:
stateTask.edit(true);
break;
case ISSUE_REOPEN:
stateTask.edit(false);
break;
}
}

}
6 changes: 6 additions & 0 deletions inspector/test/java_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ def test_parse_anonymous_class(self):
self.assertEqual(len(mth4.nested_classes), 1)
self.assertEqual(len(mth4.nested_functions), 0)

def test_switch_block(self):
sf = SourceFile.build_source_file(os.path.join(self.data_path, 'sample_sources', '8.java'))
self.assertEqual(unicode(sf), u'Java SourceFile: 8 imports, 1 classes')
aclass1 = sf.get_class('SwitchClass1')
self.assertEqual(len(aclass1.fields), 4)


class TestParseInternals(unittest.TestCase):
def test_visibility_parse(self):
Expand Down

0 comments on commit 4d5c731

Please sign in to comment.