(options): Added --complexity.
(flag_complexity): New global.
(main): Call `report'.
* parse-scan.y (complexity): New global.
(if_then_statement, if_then_else_statement,
if_then_else_statement_nsi, switch_block_statement_group,
while_expression, do_statement, for_begin, continue_statement,
throw_statement, catch_clause, finally, method_invocation,
conditional_and_expression, conditional_or_expression,
conditional_expression): Update complexity.
(reset_report): Reset complexity.
(report): New function.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@37595
138bc75d-0d04-0410-961f-
82ee72b054a4
2000-11-20 Tom Tromey <tromey@cygnus.com>
+ * jv-scan.c (help): Document --complexity.
+ (options): Added --complexity.
+ (flag_complexity): New global.
+ (main): Call `report'.
+ * parse-scan.y (complexity): New global.
+ (if_then_statement, if_then_else_statement,
+ if_then_else_statement_nsi, switch_block_statement_group,
+ while_expression, do_statement, for_begin, continue_statement,
+ throw_statement, catch_clause, finally, method_invocation,
+ conditional_and_expression, conditional_or_expression,
+ conditional_expression): Update complexity.
+ (reset_report): Reset complexity.
+ (report): New function.
+
+2000-11-20 Tom Tromey <tromey@cygnus.com>
+
* lex.c (yylex): Added STRICT_TK case.
* parse.y (STRICT_TK): Added.
* parse-scan.y (STRICT_TK): Added.
void fatal PARAMS ((const char *s, ...)) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
void warning PARAMS ((const char *s, ...)) ATTRIBUTE_PRINTF_1;
void gcc_obstack_init PARAMS ((struct obstack *obstack));
+void report PARAMS ((void));
static void usage PARAMS ((void)) ATTRIBUTE_NORETURN;
static void help PARAMS ((void)) ATTRIBUTE_NORETURN;
int flag_find_main = 0;
int flag_dump_class = 0;
int flag_list_filename = 0;
+int flag_complexity = 0;
int pedantic = 0;
{ "list-filename", no_argument, &flag_list_filename, 1 },
{ "list-class", no_argument, &flag_dump_class, 1 },
{ "encoding", required_argument, NULL, OPT_ENCODING },
+ { "complexity", no_argument, &flag_complexity, 1 },
{ NULL, no_argument, NULL, 0 }
};
{
printf ("Usage: jv-scan [OPTION]... FILE...\n\n");
printf ("Print useful information read from Java source files.\n\n");
+ printf (" --complexity Print cyclomatic complexity of input file\n");
printf (" --encoding NAME Specify encoding of input file\n");
printf (" --print-main Print name of class containing `main'\n");
printf (" --list-class List all classes defined in file\n");
}
/* No flags? Do nothing */
- if (!flag_find_main && !flag_dump_class)
+ if (! flag_find_main && ! flag_dump_class && ! flag_complexity)
return 0;
/* Check on bad usage */
- if (flag_find_main && flag_dump_class)
- fatal ("Options `--print-main' and `--list-class' can't be turned on at the same time");
+ if (flag_find_main + flag_dump_class + flag_complexity > 1)
+ fatal ("Only one of `--print-main', `--list-class', and `--complexity' allowed");
if (output_file && !(out = fopen (output_file, "w")))
fatal ("Can't open output file `%s'", output_file);
java_init_lex (finput, encoding);
yyparse ();
+ report ();
if (ftell (out) != ft)
fputc ('\n', out);
ft = ftell (out);
/* Record modifier uses */
static int modifier_value;
+/* Record (almost) cyclomatic complexity. */
+static int complexity;
+
/* Keeps track of number of bracket pairs after a variable declarator
id. */
static int bracket_count;
static void push_class_context PARAMS ((const char *));
static void pop_class_context PARAMS ((void));
+void report PARAMS ((void));
+
#include "lex.h"
#include "parse.h"
%}
;
if_then_statement:
- IF_TK OP_TK expression CP_TK statement
+ IF_TK OP_TK expression CP_TK statement { ++complexity; }
;
if_then_else_statement:
IF_TK OP_TK expression CP_TK statement_nsi ELSE_TK statement
+ { ++complexity; }
;
if_then_else_statement_nsi:
IF_TK OP_TK expression CP_TK statement_nsi ELSE_TK statement_nsi
+ { ++complexity; }
;
switch_statement:
;
switch_block_statement_group:
- switch_labels block_statements
+ switch_labels block_statements { ++complexity; }
;
;
while_expression:
- WHILE_TK OP_TK expression CP_TK
+ WHILE_TK OP_TK expression CP_TK { ++complexity; }
;
while_statement:
do_statement:
do_statement_begin statement WHILE_TK OP_TK expression CP_TK SC_TK
+ { ++complexity; }
;
for_statement:
;
for_begin:
- for_header for_init
+ for_header for_init { ++complexity; }
;
for_init: /* Can be empty */
| statement_expression_list
| BREAK_TK identifier SC_TK
;
+/* `continue' with a label is considered for complexity but ordinary
+ continue is not. */
continue_statement:
CONTINUE_TK SC_TK
-| CONTINUE_TK identifier SC_TK
+ | CONTINUE_TK identifier SC_TK { ++complexity; }
;
return_statement:
;
throw_statement:
- THROW_TK expression SC_TK
+ THROW_TK expression SC_TK { ++complexity; }
;
synchronized_statement:
;
catch_clause:
- CATCH_TK OP_TK formal_parameter CP_TK block
+ CATCH_TK OP_TK formal_parameter CP_TK block { ++complexity; }
;
finally:
- FINALLY_TK block
+ FINALLY_TK block { ++complexity; }
;
/* 19.12 Production from 15: Expressions */
| SUPER_TK DOT_TK identifier
;
+/* We include method invocation in the complexity measure on the
+ theory that most method calls are virtual and therefore involve a
+ decision point. */
method_invocation:
name OP_TK CP_TK
- { USE_ABSORBER; }
+ { USE_ABSORBER; ++complexity; }
| name OP_TK argument_list CP_TK
- { USE_ABSORBER; }
-| primary DOT_TK identifier OP_TK CP_TK
-| primary DOT_TK identifier OP_TK argument_list CP_TK
-| SUPER_TK DOT_TK identifier OP_TK CP_TK
-| SUPER_TK DOT_TK identifier OP_TK argument_list CP_TK
+ { USE_ABSORBER; ++complexity; }
+| primary DOT_TK identifier OP_TK CP_TK { ++complexity; }
+| primary DOT_TK identifier OP_TK argument_list CP_TK { ++complexity; }
+| SUPER_TK DOT_TK identifier OP_TK CP_TK { ++complexity; }
+| SUPER_TK DOT_TK identifier OP_TK argument_list CP_TK { ++complexity; }
;
array_access:
conditional_and_expression:
inclusive_or_expression
| conditional_and_expression BOOL_AND_TK inclusive_or_expression
+ { ++complexity; }
;
conditional_or_expression:
conditional_and_expression
| conditional_or_expression BOOL_OR_TK conditional_and_expression
+ { ++complexity; }
;
conditional_expression: /* Error handling here is weak */
conditional_or_expression
| conditional_or_expression REL_QM_TK expression REL_CL_TK conditional_expression
+ { ++complexity; }
;
assignment_expression:
}
}
+void
+report ()
+{
+ extern int flag_complexity;
+ if (flag_complexity)
+ fprintf (out, "%s %d\n", input_filename, complexity);
+}
+
/* Reset global status used by the report functions. */
void reset_report ()
previous_output = 0;
package_name = NULL;
current_class = NULL;
+ complexity = 0;
}
void