From 77c1672a1675f531bd7bd6b65a48e623b69ef2e9 Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Thu, 8 Jun 2017 13:38:54 +0200 Subject: [PATCH 01/15] Update #30 SH.MET.LineOfCode --- .../lex/SHMETLineOfCode.lex | 337 +++++++++++++----- .../tools/shell/metrics/Function.java | 124 +++++++ .../shell/metrics/FunctionLineOfCode.java | 33 ++ 3 files changed, 414 insertions(+), 80 deletions(-) create mode 100644 fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/Function.java create mode 100644 fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfCode.java diff --git a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfCode.lex b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfCode.lex index 9ba2fb89..3e577b31 100755 --- a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfCode.lex +++ b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfCode.lex @@ -15,24 +15,28 @@ package fr.cnes.analysis.tools.shell.metrics; +import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; +import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; + +import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; -import java.io.File; + +import java.util.EmptyStackException; import java.util.LinkedList; import java.util.List; +import java.util.Stack; -import org.eclipse.core.runtime.Path; +import java.util.logging.Logger; -import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; -import fr.cnes.analysis.tools.analyzer.datas.CheckResult; -import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import org.eclipse.core.runtime.Path; %% %class SHMETLineOfCode %extends AbstractChecker %public -%ignorecase %line %column @@ -40,23 +44,39 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %yylexthrow JFlexException %type List -%state AVOID, NAMING, FUNCTION, USEFUL +%state COMMENT, NAMING, BEGINFUNC, STRING, COMMAND -COMMENT_WORD = \# -FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) -SPACE = [\ \r\t\f] -VAR = [a-zA-Z][a-zA-Z0-9\_]* +COMMENT_WORD = [\#] +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f\space] +NAME = [a-zA-Z\_][a-zA-Z0-9\_]* +SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) +EXPANDED_VAR = [\$][\{](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\:\%\=\+\?\/\!\-\,\^\#\*\@]|([\[](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\/\:\%\=\+\?\!\$\-\,\^\#\*\@\[\]\{\}])+[\]]))+[\}] +VAR = {NAME}|{EXPANDED_VAR}|([\$]({NAME}|{SHELL_VAR})) +IGNORE_COMMAND = \\` +COMMAND = \` +STRING_D = \" +IGNORE_STRING_D = \\\" +STRING_S = \' +IGNORE_STRING_S = \\\' +IGNORE = {IGNORE_STRING_D} | {IGNORE_STRING_S} | {IGNORE_COMMAND} +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" %{ - String location = "MAIN PROGRAM"; - List identifiers = new LinkedList(); - float lines=0; - float linesMain=0; - float linesTotal=0; - int brackets = 0; - int functionLine = 0; - + private String location = "MAIN PROGRAM"; + private List identifiers = new LinkedList(); + private float lines=0; + private boolean emptyLine = true; + private boolean inStringSimpleQuoted = false; + private boolean inStringDoubleQuoted = false; + private int functionLine; + private float linesMain=0; + private float linesTotal=0; + private Stack functionStack = new Stack<>(); + private static final Logger LOGGER = Logger.getLogger(SHMETLineOfCode.class.getName()); public SHMETLineOfCode(){ } @@ -64,102 +84,259 @@ VAR = [a-zA-Z][a-zA-Z0-9\_]* @Override public void setInputFile(File file) throws FileNotFoundException { super.setInputFile(file); + LOGGER.info("begin method setInputFile"); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); + LOGGER.info("end method setInputFile"); } private void endLocation() throws JFlexException { - this.computeMetric(this.location, lines+1, functionLine + 1); + LOGGER.info("begin method endLocation"); + try{ + FunctionLineOfCode functionEnded = (FunctionLineOfCode) functionStack.pop(); + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] computing function :"+functionEnded.getName()+" line :"+ functionEnded.getBeginLine()+" with value : "+functionEnded.getLineOfCode()); + this.computeMetric(functionEnded.getName(), functionEnded.getLineOfCode(), functionEnded.getBeginLine()); + if(functionStack.empty()){ + linesMain+=functionEnded.getLineOfCode(); + }else{ + FunctionLineOfCode function = (FunctionLineOfCode) functionStack.peek(); + function.setLineOfCode(function.getLineOfCode()+functionEnded.getLineOfCode()); + } + }catch(EmptyStackException e){ + String errorMessage = "Class"+this.getClass().getName()+"\n"+e.getMessage()+"\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; + throw new JFlexException(new Exception(errorMessage)); + } + LOGGER.info("end method setInputFile"); + } + + private void addLines(){ + LOGGER.info("begin method addLines"); + if(!emptyLine){ + if(functionStack.empty()){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line to MAIN PROGRAM"); + linesMain++; + } else { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line to the function "+((FunctionLineOfCode) functionStack.peek()).getName()); + ((FunctionLineOfCode) functionStack.peek()).addLineOfCode(); + } + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line for the whole file"); + linesTotal++; + } + LOGGER.info("end method addLines"); } %} %eofval{ - final List list = this.fileValue.getFunctionValues(); - list.add(new FunctionValue("MAIN PROGRAM", linesMain, functionLine+1)); - fileValue.setValue(linesTotal); - return fileValue; -%eofval} -%eofval{ - this.computeMetric("MAIN PROGRAM", linesMain, functionLine+1); + if(functionStack.empty()){ + this.computeMetric("MAIN PROGRAM", linesMain, 1); + }else{ + String errorMessage = "Class"+this.getClass().getName()+"\nunreadable by analyzer, at least one function is not ending correctly.\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; + throw new JFlexException(new Exception(errorMessage)); + } this.computeMetric(null, linesTotal, 0); return getCheckResults(); %eofval} %% /************************/ - +/* COMMENT STATE */ /************************/ -/* AVOID STATE */ + + { + \n { + //Count pending the value of emptyline (as the comment might be on the right side of some code) + addLines(); + emptyLine=true; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMENT -> YYINITIAL (Transition : \\n )"); + yybegin(YYINITIAL); + } + . | {SPACE} { } + } + /************************/ - +/* YYINITIAL STATE */ +/************************/ + { - \n {yybegin(YYINITIAL);} - . {} - } + + + {COMMENT_WORD} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); + yybegin(COMMENT); + } + {FUNCTION} { + emptyLine = false; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); + yybegin(NAMING); + } + {FUNCT} { + emptyLine = false; + functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + + {FUNCSTART} { + emptyLine = false; + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); + functionStack.peek().addStarterRepetition(); + } + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for FUNCSTART \""+yytext()+"\" )"); + } + } + {FUNCEND} { + emptyLine = false; + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); + try{ + functionStack.peek().removeStarterRepetition(); + }catch(JFlexException e){ + String errorMessage = "Class"+this.getClass().getName()+"\n"+e.getMessage()+"\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; + throw new JFlexException(new Exception(errorMessage)); + } + } else { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] endLocation() for FUNCEND \""+yytext()+"\" )"); + addLines(); + emptyLine=true; + endLocation(); + } + } + } + } + {VAR} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for VAR \""+yytext()+"\" )"); + emptyLine = false; + } + {IGNORE} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); + emptyLine = false; + } + {COMMAND} { + emptyLine = false; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); + yybegin(COMMAND); + } + {STRING_S} { + emptyLine = false; + inStringSimpleQuoted = true; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING (Transition : STRING_S \""+yytext()+"\" )"); + yybegin(STRING); + } + {STRING_D} { + emptyLine = false; + inStringDoubleQuoted = true; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING (Transition : STRING_D \""+yytext()+"\" )"); + yybegin(STRING); + } + + \n { + addLines(); + emptyLine=true; + } + {SPACE} { } + . { + emptyLine = false; + } + } + /************************/ /* NAMING STATE */ /************************/ { - {VAR} {functionLine=yyline;location = yytext(); lines=0; yybegin(USEFUL);} - \n {lines=1; linesTotal++; yybegin(YYINITIAL);} - . {} + {VAR} { + emptyLine = false; + location = yytext(); + functionLine = yyline+1; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> BEGINFUNC (Transition : VAR \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + \n { + addLines(); + emptyLine = true; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : \\n )"); + yybegin(YYINITIAL); + } + . | {SPACE} {} } /************************/ -/* YYINITIAL STATE */ +/* BEGINFUNC STATE */ /************************/ - +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + { - {COMMENT_WORD} {yybegin(AVOID);} - {FUNCTION} {yybegin(NAMING);} - {FUNCT} {functionLine=yyline;location = yytext().substring(0,yytext().length()-2).trim(); lines=0; yybegin(USEFUL); } - \{ {brackets++; yybegin(USEFUL);} - \} {brackets--; - if(brackets==0 && !location.equals("MAIN PROGRAM")) { - endLocation(); - functionLine=0; - location = "MAIN PROGRAM"; - lines=0; - linesTotal++; - yybegin(AVOID); - } else { - yybegin(USEFUL); - }} - \n | {SPACE} {} - . {yybegin(USEFUL);} + \(\) {} + {FUNCSTART} { + FunctionLineOfCode function = new FunctionLineOfCode(location, functionLine, yytext()); + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for FUNCSTART \""+yytext()+"\" )"); + functionStack.push(function); + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> YYINITIAL (Transition : FUNCSTART \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + . | \n |{SPACE} { } } - /************************/ -/* USEFUL STATE */ +/* COMMAND STATE */ /************************/ - + { - {FUNCTION} {yybegin(NAMING);} - {FUNCT} {functionLine=yyline;location = yytext().substring(0,yytext().length()-2).trim(); } - \{ {brackets++;} - \} {brackets--; - if(brackets==0 && !location.equals("MAIN PROGRAM")) { - endLocation(); - functionLine=0; - location = "MAIN PROGRAM"; - lines=0; - linesTotal++; - yybegin(AVOID); - }} - \\{SPACE}*\n {} - \n {if(location.equals("MAIN PROGRAM")) linesMain++; - else lines++; - linesTotal++; yybegin(YYINITIAL);} - . {} + \n { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [COMMAND] count line for \\n"); + addLines(); + } + {COMMAND} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> YYINITIAL (Transition : COMMAND \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + . | {SPACE} { } + } +/************************/ +/* STRING STATE */ +/************************/ + + { + \n { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING] count line for \\n"); + addLines(); + } + {IGNORE} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING] do nothing for IGNORE \""+yytext()+"\" )"); + } + {STRING_S} { + if(inStringSimpleQuoted){ + inStringSimpleQuoted=false; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING -> YYINITIAL (Transition : STRING_S \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + + } + {STRING_D} { + if(inStringDoubleQuoted){ + inStringDoubleQuoted=false; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING -> YYINITIAL (Transition : STRING_D \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + + } + . | {SPACE} { } } - - - /************************/ /* ERROR STATE */ /************************/ - [^] {} + [^] { + String errorMessage = "Class: "+this.getClass().getName()+"\nIllegal character <" + yytext() + ">\nFile :"+ this.getInputFile().getAbsolutePath() +"\nat line:"+yyline+" column:"+yycolumn+"\nLast word read : "+yytext(); + throw new JFlexException(new Exception(errorMessage)); + } diff --git a/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/Function.java b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/Function.java new file mode 100644 index 00000000..742fae55 --- /dev/null +++ b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/Function.java @@ -0,0 +1,124 @@ +package fr.cnes.analysis.tools.shell.metrics; + +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; + +public class Function { + private String name; + private int beginLine; + private String starter; + private int starterRepetition; + + public Function(final String pName, final int pBeginLine, final String pStarter) { + this.name = pName; + this.beginLine = pBeginLine; + this.starter = pStarter; + this.starterRepetition = 0; + } + + public void addStarterRepetition() { + starterRepetition++; + } + + public void removeStarterRepetition() throws JFlexException { + if (starterRepetition > 0) { + starterRepetition--; + } else { + throw new JFlexException( + new Exception("Count of function's starter closure is negative.")); + } + } + + public final String getFinisher() throws JFlexException { + return Function.finisherOf(this.starter); + } + + public static final String finisherOf(String str) throws JFlexException { + String functionFinisher; + switch (str) { + case "if": + functionFinisher = "fi"; + break; + case "case": + functionFinisher = "esac"; + break; + case "select": + case "for": + case "while": + case "until": + functionFinisher = "done"; + break; + case "{": + functionFinisher = "}"; + break; + case "(": + functionFinisher = ")"; + break; + case "((": + functionFinisher = "))"; + break; + case "[[": + functionFinisher = "]]"; + break; + default: + throw new JFlexException(new Exception("Function's ender unknown.")); + } + return functionFinisher; + } + + public final boolean isFinisher(String str) throws JFlexException { + return str.equals(this.getFinisher()); + } + + /** + * @return the name + */ + public final String getName() { + return name; + } + + /** + * @param name + * the name to set + */ + public final void setName(String name) { + this.name = name; + } + + /** + * @return the beginLine + */ + public final int getBeginLine() { + return beginLine; + } + + /** + * @param beginLine + * the beginLine to set + */ + public final void setBeginLine(int beginLine) { + this.beginLine = beginLine; + } + + /** + * @return the string starting the fucntion + */ + public final String getStarter() { + return starter; + } + + /** + * @param pStarter + * String starting the function + */ + public final void setStarter(String pStarter) { + this.starter = pStarter; + } + + /** + * @return the starterRepetition + */ + public final int getStarterRepetition() { + return starterRepetition; + } + +} diff --git a/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfCode.java b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfCode.java new file mode 100644 index 00000000..b1987c52 --- /dev/null +++ b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfCode.java @@ -0,0 +1,33 @@ +package fr.cnes.analysis.tools.shell.metrics; + +public class FunctionLineOfCode extends Function { + private String name; + private int beginLine; + private String starter; + private int lineOfCode; + + public FunctionLineOfCode(final String pName, final int pBeginLine, final String pStarter) { + super(pName, pBeginLine, pStarter); + lineOfCode = 0; + } + + public void addLineOfCode() { + this.lineOfCode++; + } + + /** + * @return the lineOfCode + */ + public final int getLineOfCode() { + return lineOfCode; + } + + /** + * @param lineOfCode + * the lineOfCode to set + */ + public final void setLineOfCode(int lineOfCode) { + this.lineOfCode = lineOfCode; + } + +} From a26a29b39801bbf854deba8602a0eed8de1fee49 Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Thu, 8 Jun 2017 13:43:08 +0200 Subject: [PATCH 02/15] Update #30 SH.MET.LineOfCode logger lever decreased to fine --- .../lex/SHMETLineOfCode.lex | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfCode.lex b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfCode.lex index 3e577b31..364c74d4 100755 --- a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfCode.lex +++ b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETLineOfCode.lex @@ -84,16 +84,16 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" @Override public void setInputFile(File file) throws FileNotFoundException { super.setInputFile(file); - LOGGER.info("begin method setInputFile"); + LOGGER.fine("begin method setInputFile"); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); - LOGGER.info("end method setInputFile"); + LOGGER.fine("end method setInputFile"); } private void endLocation() throws JFlexException { - LOGGER.info("begin method endLocation"); + LOGGER.fine("begin method endLocation"); try{ FunctionLineOfCode functionEnded = (FunctionLineOfCode) functionStack.pop(); - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] computing function :"+functionEnded.getName()+" line :"+ functionEnded.getBeginLine()+" with value : "+functionEnded.getLineOfCode()); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] computing function :"+functionEnded.getName()+" line :"+ functionEnded.getBeginLine()+" with value : "+functionEnded.getLineOfCode()); this.computeMetric(functionEnded.getName(), functionEnded.getLineOfCode(), functionEnded.getBeginLine()); if(functionStack.empty()){ linesMain+=functionEnded.getLineOfCode(); @@ -105,23 +105,23 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" String errorMessage = "Class"+this.getClass().getName()+"\n"+e.getMessage()+"\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; throw new JFlexException(new Exception(errorMessage)); } - LOGGER.info("end method setInputFile"); + LOGGER.fine("end method setInputFile"); } private void addLines(){ - LOGGER.info("begin method addLines"); + LOGGER.fine("begin method addLines"); if(!emptyLine){ if(functionStack.empty()){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line to MAIN PROGRAM"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line to MAIN PROGRAM"); linesMain++; } else { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line to the function "+((FunctionLineOfCode) functionStack.peek()).getName()); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line to the function "+((FunctionLineOfCode) functionStack.peek()).getName()); ((FunctionLineOfCode) functionStack.peek()).addLineOfCode(); } - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line for the whole file"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line for the whole file"); linesTotal++; } - LOGGER.info("end method addLines"); + LOGGER.fine("end method addLines"); } %} @@ -147,7 +147,7 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" //Count pending the value of emptyline (as the comment might be on the right side of some code) addLines(); emptyLine=true; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMENT -> YYINITIAL (Transition : \\n )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMENT -> YYINITIAL (Transition : \\n )"); yybegin(YYINITIAL); } . | {SPACE} { } @@ -161,19 +161,19 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" {COMMENT_WORD} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); yybegin(COMMENT); } {FUNCTION} { emptyLine = false; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); yybegin(NAMING); } {FUNCT} { emptyLine = false; functionLine = yyline+1; location = yytext().substring(0,yytext().length()-2).trim(); - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); yybegin(BEGINFUNC); } @@ -181,10 +181,10 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" emptyLine = false; if(!functionStack.empty()){ if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); functionStack.peek().addStarterRepetition(); } - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for FUNCSTART \""+yytext()+"\" )"); } } {FUNCEND} { @@ -192,7 +192,7 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" if(!functionStack.empty()){ if(functionStack.peek().isFinisher(yytext())){ if(functionStack.peek().getStarterRepetition()>0) { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); try{ functionStack.peek().removeStarterRepetition(); }catch(JFlexException e){ @@ -200,7 +200,7 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" throw new JFlexException(new Exception(errorMessage)); } } else { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] endLocation() for FUNCEND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] endLocation() for FUNCEND \""+yytext()+"\" )"); addLines(); emptyLine=true; endLocation(); @@ -209,28 +209,28 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" } } {VAR} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for VAR \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for VAR \""+yytext()+"\" )"); emptyLine = false; } {IGNORE} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); emptyLine = false; } {COMMAND} { emptyLine = false; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); yybegin(COMMAND); } {STRING_S} { emptyLine = false; inStringSimpleQuoted = true; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING (Transition : STRING_S \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING (Transition : STRING_S \""+yytext()+"\" )"); yybegin(STRING); } {STRING_D} { emptyLine = false; inStringDoubleQuoted = true; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING (Transition : STRING_D \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING (Transition : STRING_D \""+yytext()+"\" )"); yybegin(STRING); } @@ -254,13 +254,13 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" emptyLine = false; location = yytext(); functionLine = yyline+1; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> BEGINFUNC (Transition : VAR \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> BEGINFUNC (Transition : VAR \""+yytext()+"\" )"); yybegin(BEGINFUNC); } \n { addLines(); emptyLine = true; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : \\n )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : \\n )"); yybegin(YYINITIAL); } . | {SPACE} {} @@ -279,9 +279,9 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" \(\) {} {FUNCSTART} { FunctionLineOfCode function = new FunctionLineOfCode(location, functionLine, yytext()); - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for FUNCSTART \""+yytext()+"\" )"); functionStack.push(function); - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> YYINITIAL (Transition : FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> YYINITIAL (Transition : FUNCSTART \""+yytext()+"\" )"); yybegin(YYINITIAL); } . | \n |{SPACE} { } @@ -292,11 +292,11 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" { \n { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [COMMAND] count line for \\n"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [COMMAND] count line for \\n"); addLines(); } {COMMAND} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> YYINITIAL (Transition : COMMAND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> YYINITIAL (Transition : COMMAND \""+yytext()+"\" )"); yybegin(YYINITIAL); } . | {SPACE} { } @@ -307,16 +307,16 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" { \n { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING] count line for \\n"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING] count line for \\n"); addLines(); } {IGNORE} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING] do nothing for IGNORE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING] do nothing for IGNORE \""+yytext()+"\" )"); } {STRING_S} { if(inStringSimpleQuoted){ inStringSimpleQuoted=false; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING -> YYINITIAL (Transition : STRING_S \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING -> YYINITIAL (Transition : STRING_S \""+yytext()+"\" )"); yybegin(YYINITIAL); } @@ -324,7 +324,7 @@ FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" {STRING_D} { if(inStringDoubleQuoted){ inStringDoubleQuoted=false; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING -> YYINITIAL (Transition : STRING_D \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING -> YYINITIAL (Transition : STRING_D \""+yytext()+"\" )"); yybegin(YYINITIAL); } From 9ae548f382babc2702fbec2c1a4efaefe44e7ed3 Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Mon, 12 Jun 2017 18:22:37 +0200 Subject: [PATCH 03/15] Update #30 javadoc of Function and FunctionLineOfCode class --- .../tools/shell/metrics/Function.java | 76 ++++++++++++++++++- .../shell/metrics/FunctionLineOfCode.java | 30 ++++++-- 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/Function.java b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/Function.java index 742fae55..36405626 100644 --- a/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/Function.java +++ b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/Function.java @@ -2,12 +2,56 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +/** + * This class contains data that are commonly used by metrics to identify a + * SHELL function. This can be useful to locate a function and be implemented to + * include special details in it. + * + *

The starter repetition

+ *

+ * The {@link #starterRepetition} attribute must be used to count how many times + * a structure of control inside the function (that isn't a function itself) is + * being started while having the same closing as the instantiated + * {@link Function}. This way, it's possible to define on a function element + * parsing if it's intended to close the function or a control structure inside + * of the function. + *

+ *

Exceptions

+ *

+ * This class throws only {@link JFlexException} to fulfill analyzer + * independence of plugging in extension. It's thrown when : + *

    + *
  • It's not possible to reach a finisher for a string requested + *
  • While trying to reduce the number of repetition of the starter while it's + * value is zero or less
  • + *
+ * + * + * @since 3.0 + */ public class Function { + /** Function's name */ private String name; + /** Function's line */ private int beginLine; + /** Function starter */ private String starter; + /** + * Number of control structure having the same closing as the function's one + * inside the function + */ private int starterRepetition; + /** + * Constructor for {@link Function} object. + * + * @param pName + * name of the function + * @param pBeginLine + * line number of the function + * @param pStarter + * element starting the function's body. + */ public Function(final String pName, final int pBeginLine, final String pStarter) { this.name = pName; this.beginLine = pBeginLine; @@ -15,10 +59,21 @@ public Function(final String pName, final int pBeginLine, final String pStarter) this.starterRepetition = 0; } + /** + * Increment the number of structure having the same closing as the current + * function + */ public void addStarterRepetition() { starterRepetition++; } + /** + * Decrement the number of structure having same closing as the current + * function. To use on the closing of one of them. + * + * @throws JFlexException + * when the number of repetition below or equal zero. + */ public void removeStarterRepetition() throws JFlexException { if (starterRepetition > 0) { starterRepetition--; @@ -28,10 +83,23 @@ public void removeStarterRepetition() throws JFlexException { } } + /** + * @return the {@link String} element that would close the function. + * @throws JFlexException + */ public final String getFinisher() throws JFlexException { return Function.finisherOf(this.starter); } + /** + * @param str + * the {@link String} beginning a control structure or a + * function. + * @return the {@link String} which should be considered as the function + * closer of the parameter + * @throws JFlexException + * when no finisher can be recognized from the parameter. + */ public static final String finisherOf(String str) throws JFlexException { String functionFinisher; switch (str) { @@ -60,11 +128,17 @@ public static final String finisherOf(String str) throws JFlexException { functionFinisher = "]]"; break; default: - throw new JFlexException(new Exception("Function's ender unknown.")); + throw new JFlexException(new Exception("Function's finisher unknown.")); } return functionFinisher; } + /** + * @param str + * the string to compare + * @return if the parameter can close the function or not. + * @throws JFlexException + */ public final boolean isFinisher(String str) throws JFlexException { return str.equals(this.getFinisher()); } diff --git a/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfCode.java b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfCode.java index b1987c52..b419d36e 100644 --- a/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfCode.java +++ b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfCode.java @@ -1,16 +1,34 @@ package fr.cnes.analysis.tools.shell.metrics; +/** + * This class is intended to count the number of line of a file in SHELL + * language. To use this class, read the {@link Function} documentation. + * + * @since 3.0 + */ public class FunctionLineOfCode extends Function { - private String name; - private int beginLine; - private String starter; - private int lineOfCode; + /** Number of line of code of the function */ + private float lineOfCode; + /** + * Constructor mostly for parameter of {@link Function} class. Line of code + * is set to zero on new instance. + * + * @param pName + * of the function + * @param pBeginLine + * of the function + * @param pStarter + * {@link String} of the function's body + */ public FunctionLineOfCode(final String pName, final int pBeginLine, final String pStarter) { super(pName, pBeginLine, pStarter); lineOfCode = 0; } + /** + * Increment number of line of code. + */ public void addLineOfCode() { this.lineOfCode++; } @@ -18,7 +36,7 @@ public void addLineOfCode() { /** * @return the lineOfCode */ - public final int getLineOfCode() { + public final float getLineOfCode() { return lineOfCode; } @@ -26,7 +44,7 @@ public final int getLineOfCode() { * @param lineOfCode * the lineOfCode to set */ - public final void setLineOfCode(int lineOfCode) { + public final void setLineOfCode(float lineOfCode) { this.lineOfCode = lineOfCode; } From 4f9e7b2e2727cab2686adde68ddbb6d54381d58d Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Mon, 12 Jun 2017 18:23:16 +0200 Subject: [PATCH 04/15] Update #30 Adding of SH.MET.RatioComment --- .../lex/SHMETRatioComment.lex | 435 ++++++++++++------ .../shell/metrics/FunctionLineOfComment.java | 51 ++ 2 files changed, 348 insertions(+), 138 deletions(-) create mode 100644 fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfComment.java diff --git a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETRatioComment.lex b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETRatioComment.lex index d7939564..ac7d9c9b 100755 --- a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETRatioComment.lex +++ b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETRatioComment.lex @@ -8,31 +8,35 @@ /* This file is used to generate a metric checker for comment's rate. For */ /* further information on this, we advise you to refer to CNES manual dealing */ /* with metrics. */ -/* As many comments have been done on the RATEComment.lex file, this file */ +/* As many comments have been done on the MAXImbric.lex file, this file */ /* will restrain its comments on modifications. */ /* */ /********************************************************************************/ package fr.cnes.analysis.tools.shell.metrics; +import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; +import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; + +import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; -import java.io.File; + +import java.util.EmptyStackException; import java.util.LinkedList; import java.util.List; +import java.util.Stack; -import org.eclipse.core.runtime.Path; +import java.util.logging.Logger; -import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; -import fr.cnes.analysis.tools.analyzer.datas.CheckResult; -import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import org.eclipse.core.runtime.Path; %% %class SHMETRatioComment %extends AbstractChecker %public -%ignorecase %line %column @@ -40,23 +44,42 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %yylexthrow JFlexException %type List -%state COMMENT, AVOID, NAMING, FUNCTION, USEFUL - -COMMENT_WORD = \# -FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) -SPACE = [\ \r\t\f] -VAR = [a-zA-Z][a-zA-Z0-9\_]* - +%state COMMENT, NAMING, BEGINFUNC, STRING, COMMAND +COMMENT_WORD = [\#] +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f\space] +NAME = [a-zA-Z\_][a-zA-Z0-9\_]* +SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) +EXPANDED_VAR = [\$][\{](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\:\%\=\+\?\/\!\-\,\^\#\*\@]|([\[](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\/\:\%\=\+\?\!\$\-\,\^\#\*\@\[\]\{\}])+[\]]))+[\}] +VAR = {NAME}|{EXPANDED_VAR}|([\$]({NAME}|{SHELL_VAR})) +IGNORE_COMMAND = \\` +COMMAND = \` +STRING_D = \" +IGNORE_STRING_D = \\\" +STRING_S = \' +IGNORE_STRING_S = \\\' +IGNORE = {IGNORE_STRING_D} | {IGNORE_STRING_S} | {IGNORE_COMMAND} +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" %{ - String location = "MAIN PROGRAM"; - List linesType = new LinkedList(); - List locationsLines = new LinkedList<>(); - List locations = new LinkedList(); - int brackets = 0; - + private String location = "MAIN PROGRAM"; + private List identifiers = new LinkedList(); + private float lines=0; + private boolean emptyLine = true; + private boolean inStringSimpleQuoted = false; + private boolean inStringDoubleQuoted = false; + private float lastLinesCommented = 0; + private int functionLine; + private float commentLinesMain=0; + private float commentLinesTotal=0; + private float linesMain=0; + private float linesTotal=0; + private Stack functionStack = new Stack<>(); + private static final Logger LOGGER = Logger.getLogger(SHMETRatioComment.class.getName()); public SHMETRatioComment(){ } @@ -64,170 +87,306 @@ VAR = [a-zA-Z][a-zA-Z0-9\_]* @Override public void setInputFile(File file) throws FileNotFoundException { super.setInputFile(file); + LOGGER.fine("begin method setInputFile"); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); + LOGGER.fine("end method setInputFile"); } - private float getComments(int indexOriginal) { - float comments = 0; - // comments before the function -> header - int index = indexOriginal - 1; - while (index >= 0 && linesType.get(index).equals("comment")) { - comments++; - index--; - } - //comments inside the function - index = indexOriginal + 1; - while ( index header - int index = indexOriginal - 1; - while (index >= 0 && linesType.get(index).equals("comment")) { - lines++; - index--; + private void endLocation() throws JFlexException { + LOGGER.fine("begin method endLocation"); + try{ + FunctionLineOfComment functionFinished = functionStack.pop(); + if(functionFinished.getLineOfCode() > 10){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] computing function :"+functionFinished.getName()+" line :"+ functionFinished.getBeginLine()+" with value : "+(functionFinished.getLineOfComment()/functionFinished.getLineOfCode())*100); + this.computeMetric(functionFinished.getName(), (functionFinished.getLineOfComment()/(functionFinished.getLineOfCode()+functionFinished.getLineOfComment()))*100, functionFinished.getBeginLine()); + } else { + this.computeMetric(functionFinished.getName(), Float.NaN, functionFinished.getBeginLine()); + } + if(functionStack.empty()){ + linesMain+=functionFinished.getLineOfCode(); + commentLinesMain+=functionFinished.getLineOfComment(); + }else{ + FunctionLineOfComment function = functionStack.peek(); + function.setLineOfCode(function.getLineOfCode()+functionFinished.getLineOfCode()); + function.setLineOfComment(function.getLineOfComment()+functionFinished.getLineOfComment()); + } + }catch(EmptyStackException e){ + String errorMessage = "Class"+this.getClass().getName()+"\n"+e.getMessage()+"\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; + throw new JFlexException(new Exception(errorMessage)); } - //lines inside the function - index = indexOriginal + 1; - while (index0 && !found; i--) { - if (linesType.get(i).equals("finFunction")) { - // count the number of comments and lines - float comments = getComments(i+1); - float lines = getLines(i+1); - // insert the rate into list - this.computeMetric("MAIN PROGRAM", comments/lines, 1); - found=true; + private void addLines(){ + LOGGER.fine("begin method addLines"); + if(!emptyLine){ + if(functionStack.empty()){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line to MAIN PROGRAM"); + linesMain++; + } else { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line to the function "+ functionStack.peek().getName()); + functionStack.peek().addLineOfCode(); } + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] counting one line for the whole file"); + linesTotal++; } + LOGGER.fine("end method addLines"); } - - private void getRateCommentsFile() throws JFlexException { - float comments = 0; - float lines = 0; - for (int i=0; i 10) { + this.computeMetric("MAIN PROGRAM", (commentLinesMain/(linesMain+commentLinesMain))*100, 1); + }else{ + this.computeMetric("MAIN PROGRAM", Float.NaN, 1); + } + }else{ + String errorMessage = "Class"+this.getClass().getName()+"\nunreadable by analyzer, at least one function is not ending correctly.\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; + throw new JFlexException(new Exception(errorMessage)); + } + if(linesTotal > 10){ + this.computeMetric(null, (commentLinesTotal/(linesTotal+commentLinesTotal))*100, 0); + }else{ + this.computeMetric(null, Float.NaN, 0); + } return getCheckResults(); %eofval} - %% -/************************/ - - /************************/ /* COMMENT STATE */ /************************/ { - \n {linesType.add("comment"); yybegin(YYINITIAL);} - . {} + \n { + lastLinesCommented++; + //Count pending the value of emptyline (as the comment might be on the right side of some code) + addLines(); + addCommentLines(); + emptyLine=true; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMENT -> YYINITIAL (Transition : \\n )"); + yybegin(YYINITIAL); + } + . | {SPACE} { } } - + /************************/ -/* AVOID STATE */ +/* YYINITIAL STATE */ /************************/ - + { - \n {yybegin(YYINITIAL);} - . {} + + + {COMMENT_WORD} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); + yybegin(COMMENT); + } + {FUNCTION} { + emptyLine = false; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); + yybegin(NAMING); + } + {FUNCT} { + emptyLine = false; + functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + + {FUNCSTART} { + emptyLine = false; + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); + functionStack.peek().addStarterRepetition(); + } + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for FUNCSTART \""+yytext()+"\" )"); + } + } + {FUNCEND} { + lastLinesCommented=0; + emptyLine = false; + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); + try{ + functionStack.peek().removeStarterRepetition(); + }catch(JFlexException e){ + String errorMessage = "Class"+this.getClass().getName()+"\n"+e.getMessage()+"\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; + throw new JFlexException(new Exception(errorMessage)); + } + } else { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] endLocation() for FUNCEND \""+yytext()+"\" )"); + addLines(); + emptyLine=true; + endLocation(); + } + } + } + } + {VAR} { + lastLinesCommented=0; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for VAR \""+yytext()+"\" )"); + emptyLine = false; + } + {IGNORE} { + lastLinesCommented=0; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); + emptyLine = false; + } + {COMMAND} { + lastLinesCommented=0; + emptyLine = false; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); + yybegin(COMMAND); + } + {STRING_S} { + lastLinesCommented=0; + emptyLine = false; + inStringSimpleQuoted = true; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING (Transition : STRING_S \""+yytext()+"\" )"); + yybegin(STRING); + } + {STRING_D} { + lastLinesCommented=0; + emptyLine = false; + inStringDoubleQuoted = true; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING (Transition : STRING_D \""+yytext()+"\" )"); + yybegin(STRING); + } + + \n { + lastLinesCommented=0; + addLines(); + emptyLine=true; + } + {SPACE} { } + . { + lastLinesCommented=0; + emptyLine = false; + } } + /************************/ /* NAMING STATE */ /************************/ { - {VAR} {location = yytext(); locations.add(location);locationsLines.add(yyline+1);} - \{ {brackets++;} - \n {linesType.add("function"); - yybegin(YYINITIAL); + {VAR} { + emptyLine = false; + location = yytext(); + functionLine = yyline+1; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> BEGINFUNC (Transition : VAR \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + \n { + addLines(); + emptyLine = true; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : \\n )"); + yybegin(YYINITIAL); } - . {} + . | {SPACE} {} } /************************/ -/* YYINITIAL STATE */ +/* BEGINFUNC STATE */ /************************/ - +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + { - {COMMENT_WORD} {yybegin(COMMENT);} - {FUNCTION} {yybegin(NAMING);} - {FUNCT} {location=yytext().substring(0,yytext().length()-2).trim(); locations.add(location);locationsLines.add(yyline+1); yybegin(NAMING);} - {VAR} {yybegin(USEFUL);} - \{ {brackets++; yybegin(USEFUL);} - \} {brackets--; - if(brackets==0 && !location.equals("MAIN PROGRAM")) { - linesType.add("finFunction"); - location = "MAIN PROGRAM"; - yybegin(AVOID); - } else { - yybegin(USEFUL); - }} - {SPACE} {} - \n {linesType.add("empty");} - . {yybegin(USEFUL);} + \(\) {} + {FUNCSTART} { + FunctionLineOfComment function = new FunctionLineOfComment(location, functionLine, yytext()); + if(lastLinesCommented>0){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] Transfering "+ lastLinesCommented +" lines detected as header comment from the last function to the new one. )"); + if(functionStack.empty()){ + commentLinesMain-=lastLinesCommented; + }else{ + functionStack.peek().setLineOfComment(functionStack.peek().getLineOfComment() - lastLinesCommented); + } + function.setLineOfComment(lastLinesCommented); + lastLinesCommented = 0; + } + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for FUNCSTART \""+yytext()+"\" )"); + functionStack.push(function); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> YYINITIAL (Transition : FUNCSTART \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + . | \n |{SPACE} { } + } +/************************/ +/* COMMAND STATE */ +/************************/ + + { + \n { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [COMMAND] count line for \\n"); + addLines(); + } + {COMMAND} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> YYINITIAL (Transition : COMMAND \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + . | {SPACE} { } } - /************************/ -/* USEFUL STATE */ +/* STRING STATE */ /************************/ - + { - {FUNCTION} {yybegin(NAMING);} - {FUNCT} {location=yytext().substring(0,yytext().length()-2).trim(); locations.add(location);locationsLines.add(yyline+1); yybegin(NAMING);} - {VAR} {} - \{ {brackets++;} - \} {brackets--; - if(brackets==0 && !location.equals("MAIN PROGRAM")) { - linesType.add("finFunction"); - location = "MAIN PROGRAM"; - yybegin(AVOID); - }} - \n {linesType.add("line"); yybegin(YYINITIAL);} - . {} + \n { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING] count line for \\n"); + addLines(); + } + {IGNORE} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING] do nothing for IGNORE \""+yytext()+"\" )"); + } + {STRING_S} { + if(inStringSimpleQuoted){ + inStringSimpleQuoted=false; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING -> YYINITIAL (Transition : STRING_S \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + + } + {STRING_D} { + if(inStringDoubleQuoted){ + inStringDoubleQuoted=false; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING -> YYINITIAL (Transition : STRING_D \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + + } + . | {SPACE} { } } /************************/ /* ERROR STATE */ /************************/ - [^] {} + [^] { + String errorMessage = "Class: "+this.getClass().getName()+"\nIllegal character <" + yytext() + ">\nFile :"+ this.getInputFile().getAbsolutePath() +"\nat line:"+yyline+" column:"+yycolumn+"\nLast word read : "+yytext(); + throw new JFlexException(new Exception(errorMessage)); + } + diff --git a/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfComment.java b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfComment.java new file mode 100644 index 00000000..39d4b041 --- /dev/null +++ b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionLineOfComment.java @@ -0,0 +1,51 @@ +package fr.cnes.analysis.tools.shell.metrics; + +/** + * This class is intended to compute metric counting line of comment of a + * function. To use this class read the {@link Function} and + * {@link FunctionLineOfCode} specification first. + * + * @since 3.0 + */ +public class FunctionLineOfComment extends FunctionLineOfCode { + /** Number of line of comment in the function */ + private float lineOfComment; + + /** + * Constructor mostly for parameter of {@link Function} class. Line of + * comment is set to zero on new instance. + * + * @param pName + * of the function + * @param pBeginLine + * of the function + * @param pStarter + * {@link String} of the function's body + */ + public FunctionLineOfComment(final String pName, final int pBeginLine, final String pStarter) { + super(pName, pBeginLine, pStarter); + lineOfComment = 0; + } + + /** + * Increment the number of lines of comment. + */ + public void addLineOfComment() { + this.lineOfComment++; + } + + /** + * @return the lineOfComment + */ + public final float getLineOfComment() { + return lineOfComment; + } + + /** + * @param lineOfCode + * the lineOfComment to set + */ + public final void setLineOfComment(float pLineOfComment) { + this.lineOfComment = pLineOfComment; + } +} From b89039f56e40ba30723797589bb6a08489090161 Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Tue, 13 Jun 2017 17:02:40 +0200 Subject: [PATCH 05/15] Update #30 adding SH.MET.Nesting rule Note : The method used to compute the metric here is to consider each function independently of the nesting of it's parents one. This method must be validated. --- .../lex/SHMETNesting.lex | 336 +++++++++++++----- .../tools/shell/metrics/FunctionNesting.java | 146 ++++++++ 2 files changed, 395 insertions(+), 87 deletions(-) create mode 100644 fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionNesting.java diff --git a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETNesting.lex b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETNesting.lex index ab941b2a..d3021754 100755 --- a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETNesting.lex +++ b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETNesting.lex @@ -15,21 +15,23 @@ package fr.cnes.analysis.tools.shell.metrics; +import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; +import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; + +import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; -import java.io.File; +import java.util.EmptyStackException; import java.util.LinkedList; import java.util.List; +import java.util.Stack; +import java.util.logging.Logger; import org.eclipse.core.runtime.Path; -import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; -import fr.cnes.analysis.tools.analyzer.datas.CheckResult; -import fr.cnes.analysis.tools.analyzer.exception.JFlexException; - - %% %class SHMETNesting @@ -42,36 +44,36 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %yylexthrow JFlexException %type List +%state COMMENT, NAMING, BEGINFUNC, STRING_DOUBLE, STRING_SIMPLE, COMMAND -%state COMMENT, NAMING, FUNCTION - -COMMENT_WORD = \# -FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) -SPACE = [\ \r\t\f] -VAR = [a-zA-Z0-9\_\-]+ -STRING = \'[^\']*\' | \"[^\"]*\" -OPTCHAR = \# | \! | % | \* | @ | \^ | \' | , | \/ | : | = | \+ | \? | \[ | \] -VARCOMP = {OPTCHAR} | (\$)?{VAR} | \$\{ {VAR} \} -EXTENDEDVAR = \$\{ {VARCOMP}+ \} - -IMBRIC = "while" | "for" | "until" | - "if" | "case" -END_IMBRIC = "done" | "fi" | "esac" -ELSE = "else" | "elif" - -IGNORE = "EOF" [^]* "EOF" - +COMMENT_WORD = [\#] +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f\space] +NAME = [a-zA-Z\_][a-zA-Z0-9\_]* +SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) +EXPANDED_VAR = [\$][\{](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\:\%\=\+\?\/\!\-\,\^\#\*\@]|([\[](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\/\:\%\=\+\?\!\$\-\,\^\#\*\@\[\]\{\}])+[\]]))+[\}] +VAR = {NAME}|{EXPANDED_VAR}|([\$]({NAME}|{SHELL_VAR})) +IGNORE_COMMAND = \\` +COMMAND = \` +STRING_D = \" +IGNORE_STRING_D = \\\" +STRING_S = \' +IGNORE_STRING_S = \\\' +IGNORE = {IGNORE_STRING_D} | {IGNORE_STRING_S} | {IGNORE_COMMAND} +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "case" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "esac" | "done" %{ - String location = "MAIN PROGRAM"; - List identifiers = new LinkedList(); - float numImbrics = 0; - float numMaxImbrics = 0; - float numImbricsTotal = 0; - int brackets = 0; - int functionLine = 0; - + private String location = "MAIN PROGRAM"; + private List identifiers = new LinkedList(); + private Stack functionStack = new Stack<>(); + private Stack mainNestingStack = new Stack<>(); + private int mainNesting = 0; + private int mainMaxNesting = 0; + private int functionLine = 0; + private static final Logger LOGGER = Logger.getLogger(SHMETNesting.class.getName()); public SHMETNesting(){ } @@ -79,93 +81,253 @@ IGNORE = "EOF" [^]* "EOF" @Override public void setInputFile(File file) throws FileNotFoundException { super.setInputFile(file); + LOGGER.fine("begin method setInputFile"); this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); - } - - private void addImbrics() { - numImbrics++; - if(numMaxImbrics < numImbrics) { - numMaxImbrics = numImbrics; - if (numImbricsTotal < numMaxImbrics) { - numImbricsTotal = numMaxImbrics; - } - } - } - - private void deleteImbrics() { - numImbrics--; + LOGGER.fine("end method setInputFile"); } private void endLocation() throws JFlexException { - this.computeMetric(this.location, numMaxImbrics, functionLine + 1); + LOGGER.fine("begin method endLocation"); + try{ + FunctionNesting functionFinished = functionStack.pop(); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] computing function :"+functionFinished.getName()+" line :"+ functionFinished.getBeginLine()+" with value : "+functionFinished.getMaxNesting()); + this.computeMetric(functionFinished.getName(), functionFinished.getMaxNesting(), functionFinished.getBeginLine()); + }catch(EmptyStackException e){ + String errorMessage = "Class"+this.getClass().getName()+"\n"+e.getMessage()+"\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; + throw new JFlexException(new Exception(errorMessage)); + } + LOGGER.fine("end method endLocation"); } - + %} %eofval{ - this.computeMetric("MAIN PROGRAM", numMaxImbrics, functionLine+1); - this.computeMetric(null, numImbricsTotal, 0); + if(this.functionStack.empty()){ + this.computeMetric("MAIN PROGRAM", mainMaxNesting, 1); + }else{ + String errorMessage = "Class"+this.getClass().getName()+"\nunreadable by analyzer, at least one function is not ending correctly.\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; + throw new JFlexException(new Exception(errorMessage)); + } + this.computeMetric(null, mainMaxNesting, 0); return getCheckResults(); %eofval} %% -/************************/ - - - /************************/ /* COMMENT STATE */ /************************/ { - \n {yybegin(YYINITIAL);} - . {} + \n { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMENT -> YYINITIAL (Transition : \\n )"); + yybegin(YYINITIAL); + } + . | {SPACE} { } + } + +/************************/ +/* YYINITIAL STATE */ +/************************/ + + { + {COMMENT_WORD} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); + yybegin(COMMENT); + } + {FUNCTION} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); + yybegin(NAMING); + } + + {FUNCT} { + functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + + {FUNCSTART} { + + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); + functionStack.peek().addStarterRepetition(); + }else{ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] No function change for FUNCSTART \""+yytext()+"\" )"); + } + if(FunctionNesting.isNesting(yytext())){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] pushNesting() for FUNCSTART \""+yytext()+"\" )"); + this.functionStack.peek().pushNesting(yytext()); + } + }else{ + if(FunctionNesting.isNesting(yytext())){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] Handle new nesting in the main for FUNCSTART \""+yytext()+"\" )"); + this.mainNestingStack.push(yytext()); + this.mainNesting++; + if(this.mainMaxNesting < mainNesting){ + this.mainMaxNesting = mainNesting; + } + }else{ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for FUNCSTART \""+yytext()+"\" )"); + } + } + + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); + try{ + if(!functionStack.peek().getNesting().empty() && functionStack.peek().getNestingFinisher().equals(yytext())){ + functionStack.peek().popNesting(); + } + + functionStack.peek().removeStarterRepetition(); + }catch(JFlexException e){ + String errorMessage = "Class"+this.getClass().getName()+"\n"+e.getMessage()+"\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; + throw new JFlexException(new Exception(errorMessage)); + } + } else { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] endLocation() for FUNCEND \""+yytext()+"\" )"); + endLocation(); + } + }else{ + if(!functionStack.peek().getNesting().empty() && functionStack.peek().getNestingFinisher().equals(yytext())){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] popNesting() for FUNCEND \""+yytext()+"\" )"); + functionStack.peek().popNesting(); + }else{ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] Doing nothing on imbrication for FUNCEND \""+yytext()+"\" )"); + } + } + + }else{ + if(!this.mainNestingStack.empty() && FunctionNesting.nestingFinisherOf(this.mainNestingStack.peek()).equals(yytext())){ + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] Handle nesting closing in the main for FUNCEND \""+yytext()+"\" )"); + this.mainNestingStack.pop(); + this.mainNesting--; + } + } + } + {IGNORE} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); + } + {STRING_D} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_DOUBLE (Transition : STRING_D \""+yytext()+"\" )"); + yybegin(STRING_DOUBLE); + } + {STRING_S} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_SIMPLE (Transition : STRING_S \""+yytext()+"\" )"); + yybegin(STRING_SIMPLE); + } + {COMMAND} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); + yybegin(COMMAND); + } + + {VAR} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); + } + + + \n | {SPACE} | . {} } +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING_S] do nothing for IGNORE \""+yytext()+"\" )"); + + } + {STRING_S} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_S -> YYINITIAL (Transition STRING_S : \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + . | {SPACE} | \n {} + } +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING_DOUBLE] do nothing for IGNORE \""+yytext()+"\" )"); + + } + {STRING_D} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_DOUBLE -> YYINITIAL (Transition STRING_D : \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + . | {SPACE} | \n {} + } +/************************/ +/* COMMAND STATE */ +/************************/ + + { + {IGNORE} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [COMMAND] do nothing for IGNORE \""+yytext()+"\" )"); + + } + {COMMAND} { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> YYINITIAL (Transition COMMAND : \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + . | {SPACE} | \n {} + } /************************/ /* NAMING STATE */ /************************/ { - {VAR} {functionLine = yyline; location = yytext(); yybegin(YYINITIAL);} - \n {yybegin(YYINITIAL);} - . {} + {VAR} { + location = yytext(); + functionLine = yyline+1; + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> BEGINFUNC (Transition : VAR \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + \n { + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : \\n )"); + yybegin(YYINITIAL); + } + . | {SPACE} {} } /************************/ -/* YYINITIAL STATE */ +/* BEGINFUNC STATE */ /************************/ - +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + { - {COMMENT_WORD} {yybegin(COMMENT);} - {FUNCTION} {yybegin(NAMING);} - {FUNCT} {functionLine = yyline; location = yytext().substring(0,yytext().length()-2).trim(); } - {STRING} {} - {IMBRIC} {addImbrics();} - {ELSE} {deleteImbrics(); addImbrics();} - {END_IMBRIC} {deleteImbrics();} - {VAR}(\=)? {} - {EXTENDEDVAR} {} - \{ (\#)? {brackets++;} - \} {brackets--; - if(brackets==0 && !location.equals("MAIN PROGRAM")) { - endLocation(); - functionLine=0; - location = "MAIN PROGRAM"; - numMaxImbrics=0; - numImbrics=0; - }} - {VAR} {} - {IGNORE} {} - [^] {} + \(\) {} + {FUNCSTART} { + FunctionNesting function; + if(this.functionStack.empty()){ + function = new FunctionNesting(location, functionLine, yytext(), 1, 1); + }else{ + function = new FunctionNesting(location, functionLine, yytext(), 1, 1); + } + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for FUNCSTART \""+yytext()+"\" )"); + functionStack.push(function); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> YYINITIAL (Transition : FUNCSTART \""+yytext()+"\" )"); + yybegin(YYINITIAL); + } + . | \n |{SPACE} { } } - - - /************************/ /* ERROR STATE */ /************************/ - [^] {} + [^] { + String errorMessage = "Class: "+this.getClass().getName()+"\nIllegal character <" + yytext() + ">\nFile :"+ this.getInputFile().getAbsolutePath() +"\nat line:"+yyline+" column:"+yycolumn+"\nLast word read : "+yytext(); + throw new JFlexException(new Exception(errorMessage)); + } diff --git a/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionNesting.java b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionNesting.java new file mode 100644 index 00000000..a98cabe3 --- /dev/null +++ b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionNesting.java @@ -0,0 +1,146 @@ +package fr.cnes.analysis.tools.shell.metrics; + +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; +import java.util.Stack; + +/** + * This class is intended to compute Nesting of a function for SHELL language. + * To use it, please read first {@link Function} documentation. + * + * @since 3.0 + */ +public class FunctionNesting extends Function { + + /** Element nested in the function */ + private Stack nesting; + /** + * Maximal number of element nested inside the function (including function + * nesting) + */ + private int maxNesting; + /** + * Number of element nested in the function and not closed during static + * analysis. + */ + private int currentNesting; + + /** + * Constructor + * + * @param pName + * of the function + * @param pBeginLine + * of the function + * @param pStarter + * {@link String} of the function's body + * @param pInitialMaxValue + * initial value of the maximal nesting + * @param pInitialNesting + * initial value of nesting on new instance. + */ + public FunctionNesting(String pName, int pBeginLine, String pStarter, int pInitialMaxValue, + int pInitialNesting) { + super(pName, pBeginLine, pStarter); + this.nesting = new Stack<>(); + this.maxNesting = pInitialMaxValue; + this.currentNesting = pInitialNesting; + } + + public static final boolean isNesting(String str) { + return str.equals("while") | str.equals("for") | str.equals("until") | str.equals("select") + | str.equals("if") | str.equals("case"); + } + + public static final String nestingFinisherOf(String str) throws JFlexException { + String nestingFinisher; + switch (str) { + case "while": + case "for": + case "until": + case "select": + nestingFinisher = "done"; + break; + case "if": + nestingFinisher = "fi"; + break; + case "case": + nestingFinisher = "esac"; + break; + default: + throw new JFlexException(new Exception("Nesting finisher unknown.")); + } + return nestingFinisher; + } + + public void pushNesting(String nestingBeginner) { + this.nesting.push(nestingBeginner); + this.currentNesting++; + if (this.currentNesting > this.maxNesting) { + this.maxNesting = this.currentNesting; + } + } + + public String popNesting() throws JFlexException { + if (!this.nesting.empty()) { + this.currentNesting--; + return this.nesting.pop(); + } else { + throw new JFlexException(new Exception("Pop is impossible because the stack is empty")); + + } + + } + + public boolean isNestingFinisher(String str) throws JFlexException { + return FunctionNesting.finisherOf(this.nesting.peek()).equals(str); + } + + public String getNestingFinisher() throws JFlexException { + return FunctionNesting.finisherOf(this.nesting.peek()); + } + + /** + * @return the maxNesting + */ + public final int getMaxNesting() { + return maxNesting; + } + + /** + * @param maxNesting + * the maxNesting to set + */ + public final void setMaxNesting(int maxNesting) { + this.maxNesting = maxNesting; + } + + /** + * @return the currentNesting + */ + public final int getCurrentNesting() { + return currentNesting; + } + + /** + * @param currentNesting + * the currentNesting to set + */ + public final void setCurrentNesting(int currentNesting) { + this.currentNesting = currentNesting; + } + + /** + * @return the nesting + */ + public final Stack getNesting() { + return nesting; + } + + /** + * @param nesting + * the nesting to set + */ + public final void setNesting(Stack nesting) { + this.nesting = nesting; + } +} From 44af9f587129027640c30cf19b07a1d91dc56afe Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Thu, 6 Jul 2017 16:39:58 +0200 Subject: [PATCH 06/15] Fix #45 Results stored in views are not cleared on clear command --- .../src/fr/cnes/analysis/tools/ui/view/MetricsView.java | 1 + .../src/fr/cnes/analysis/tools/ui/view/ViolationsView.java | 1 + 2 files changed, 2 insertions(+) diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java index d2dd1e3c..806612d0 100755 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java @@ -301,6 +301,7 @@ public int compare(final CheckResult value1, final CheckResult value2) { * necessarily used) */ public void clear() throws EmptyProviderException { + this.analysisResult.clear(); this.getViewer().setInput(new CheckResult[0]); this.getViewer().refresh(); } diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/ViolationsView.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/ViolationsView.java index 4e918ad9..650c9a5a 100644 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/ViolationsView.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/ViolationsView.java @@ -434,6 +434,7 @@ public void setFocus() { * necessarily used) */ public void clear() throws EmptyProviderException { + this.analysisResults.clear(); this.getViewer().setInput(new CheckResult[0]); this.getViewer().refresh(); } From 3055137ecbbfe58b9646f925f0cc52d4e8848158 Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Thu, 6 Jul 2017 17:51:02 +0200 Subject: [PATCH 07/15] Fix #37 Using imagefactory for decorators. --- .../ui/decorators/InformationDecorator.java | 3 ++- .../ui/decorators/ViolationErrorDecorator.java | 16 ++++++---------- .../ui/decorators/ViolationWarningDecorator.java | 14 +++++--------- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/InformationDecorator.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/InformationDecorator.java index d4ac6686..02de1768 100644 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/InformationDecorator.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/InformationDecorator.java @@ -5,6 +5,7 @@ /************************************************************************************************/ package fr.cnes.analysis.tools.ui.decorators; +import fr.cnes.analysis.tools.ui.images.ImageFactory; import fr.cnes.analysis.tools.ui.markers.InformationMarker; import fr.cnes.analysis.tools.ui.markers.ViolationErrorMarker; import fr.cnes.analysis.tools.ui.markers.ViolationWarningMarker; @@ -32,7 +33,7 @@ public class InformationDecorator extends LabelProvider implements ILightweightL /** * Link to the Violation Error icon */ - public static final String ICON = "/icons/logo-i-code-bleue-8x8.png"; + public static final String ICON = ImageFactory.INFO_VERY_SMALL; public static final String ID_INFORMATION_DECORATOR = "fr.cnes.tools.ui.decorators.informationdecorator"; /** diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/ViolationErrorDecorator.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/ViolationErrorDecorator.java index 09b77690..26917508 100755 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/ViolationErrorDecorator.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/ViolationErrorDecorator.java @@ -5,19 +5,17 @@ /************************************************************************************************/ package fr.cnes.analysis.tools.ui.decorators; +import fr.cnes.analysis.tools.ui.images.ImageFactory; +import fr.cnes.analysis.tools.ui.markers.ViolationErrorMarker; import java.util.List; - import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; -import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILightweightLabelDecorator; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.ui.IDecoratorManager; import org.eclipse.ui.PlatformUI; -import fr.cnes.analysis.tools.ui.markers.ViolationErrorMarker; - /** * Put a new Decoration in the files tree on the top right of an icon of a file * if a file contains a violation error marker. @@ -34,8 +32,8 @@ public class ViolationErrorDecorator extends LabelProvider implements ILightweig /** * Link to the Violation Error icon */ - public static final String ICON = "/icons/logo-i-code-rouge-8x8.png"; - public static final String ID_VIOLATION_WARNING_DECORATOR = "fr.cnes.tools.ui.decorators.violationwarningdecorator"; + public static final String ICON = ImageFactory.ERROR_VERY_SMALL; + public static final String ID_VIOLATION_ERROR_DECORATOR = "fr.cnes.tools.ui.decorators.violationerrordecorator"; /** * An Violation Error icon is being put on the top-right of the icon's file @@ -56,14 +54,12 @@ public void decorate(Object resource, final IDecoration decoration) { if (resource instanceof IResource) { final List markers = ViolationErrorMarker.findAllMarkers((IResource) resource); if (!markers.isEmpty()) { - decoration.addOverlay( - ImageDescriptor.createFromFile(ViolationErrorDecorator.class, ICON), - IDecoration.TOP_RIGHT); + decoration.addOverlay(ImageFactory.getDescriptor(ICON), IDecoration.TOP_RIGHT); // By recursivity, decorate all parents. } - } else if (!manager.getEnabled(ID_VIOLATION_WARNING_DECORATOR)) { + } else if (!manager.getEnabled(ID_VIOLATION_ERROR_DECORATOR)) { decoration.addOverlay(null); } } diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/ViolationWarningDecorator.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/ViolationWarningDecorator.java index bbb19668..0cbef807 100755 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/ViolationWarningDecorator.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/decorators/ViolationWarningDecorator.java @@ -5,18 +5,16 @@ /************************************************************************************************/ package fr.cnes.analysis.tools.ui.decorators; +import fr.cnes.analysis.tools.ui.images.ImageFactory; +import fr.cnes.analysis.tools.ui.markers.ViolationErrorMarker; +import fr.cnes.analysis.tools.ui.markers.ViolationWarningMarker; import java.util.List; - import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; -import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILightweightLabelDecorator; import org.eclipse.jface.viewers.LabelProvider; -import fr.cnes.analysis.tools.ui.markers.ViolationErrorMarker; -import fr.cnes.analysis.tools.ui.markers.ViolationWarningMarker; - /** * ViolationWarningDecorator add decorators to the file's icon when there is * markers of warning criticity and no marker of error criticity. @@ -33,7 +31,7 @@ public class ViolationWarningDecorator extends LabelProvider implements ILightwe /** * Link to the i-Code CNES Warning criticity icon. */ - public static final String ICON = "/icons/logo-i-code-orange-8x8.png"; + public static final String ICON = ImageFactory.WARNING_VERY_SMALL; /* * (non-Javadoc) @@ -57,9 +55,7 @@ public void decorate(final Object resource, final IDecoration decoration) { // If the file do not contain error marker and contain warning // markers then we put an overlay icon on the top right of the // file's icon - decoration.addOverlay( - ImageDescriptor.createFromFile(ViolationWarningDecorator.class, ICON), - IDecoration.TOP_RIGHT); + decoration.addOverlay(ImageFactory.getDescriptor(ICON), IDecoration.TOP_RIGHT); } else { // otherwise we remove the overlay if there is no violation // error neither violation warning markers. From 0fe807473d0c13a20b2053a3ea429e37ce9f955d Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Thu, 6 Jul 2017 18:01:04 +0200 Subject: [PATCH 08/15] Fix #44 Abstract class removal, metricsView directly extending ViewPart --- .../tools/ui/view/AbstractAnalysisView.java | 201 ------------------ .../analysis/tools/ui/view/MetricsView.java | 155 ++++++++++++-- 2 files changed, 136 insertions(+), 220 deletions(-) delete mode 100755 fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/AbstractAnalysisView.java diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/AbstractAnalysisView.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/AbstractAnalysisView.java deleted file mode 100755 index a519a693..00000000 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/AbstractAnalysisView.java +++ /dev/null @@ -1,201 +0,0 @@ -/************************************************************************************************/ -/* i-Code CNES is a static code analyzer. */ -/* This software is a free software, under the terms of the Eclipse Public License version 1.0. */ -/* http://www.eclipse.org/legal/epl-v10.html */ -/************************************************************************************************/ -package fr.cnes.analysis.tools.ui.view; - -import java.util.logging.Logger; - -import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.TreeViewerColumn; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeColumn; -import org.eclipse.ui.part.ViewPart; - -/** - * Abstract view defining the basis for violations and metrics results display. - * - */ -public abstract class AbstractAnalysisView extends ViewPart { - /** Logger. **/ - public final static Logger LOGGER = Logger.getLogger(AbstractAnalysisView.class.getName()); - - /** Bounds value. **/ - private transient final int[] bounds; - /** Columns titles. **/ - private transient final String[] titles; - - /** The viewer which display results. **/ - private TreeViewer viewer; - - /** - * Constructor with an integer array for table bounds and string array for - * the titles, as parameters. - * - * @param pBounds - * viewer columns' bounds - * @param pTitles - * viewer columns' titles - */ - public AbstractAnalysisView(final int[] pBounds, final String[] pTitles) { - super(); - this.bounds = pBounds.clone(); - this.titles = pTitles.clone(); - } - - /** - * Getter for the bounds. - * - * @return the bounds - */ - public int[] getBounds() { - return this.bounds.clone(); - } - - /** - * Getter for the titles. - * - * @return the titles - */ - public String[] getTitles() { - return this.titles.clone(); - } - - /** - * Getter for the viewer. - * - * @return the viewer - */ - public TreeViewer getViewer() { - return this.viewer; - } - - /** - * Setter for the viewer. - * - * @param pViewer - * this.descriptors.clone() set - */ - public void setViewer(final TreeViewer pViewer) { - this.viewer = pViewer; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt. - * widgets .Composite) - */ - @Override - public void createPartControl(final Composite parent) { - LOGGER.finest("Begin createPartControl method"); - - final GridLayout layout = new GridLayout(this.titles.length, false); - parent.setLayout(layout); - this.createViewer(parent); - - LOGGER.finest("End createPartControl method"); - } - - /** - * This method create the viewer, which is a tree table. - * - * @param parent - * the parent composite - */ - private void createViewer(final Composite parent) { - LOGGER.finest("Begin createViewer method"); - - // Defining overall style for TreeViewer - final int scrollStyle = SWT.H_SCROLL | SWT.V_SCROLL; - final int selecStyle = SWT.MULTI | SWT.FULL_SELECTION; - final int style = scrollStyle | selecStyle; - this.viewer = new TreeViewer(parent, style | SWT.FILL); - // Make headers and lines of the tree visible - final Tree tree = this.viewer.getTree(); - tree.setHeaderVisible(true); - tree.setLinesVisible(true); - - // Setting the content provider and creating columns - this.createColumns(); - - // Expand the tree - this.viewer.setAutoExpandLevel(1); - - // Add selection provider which allows to listen to each - // selection made on this viewer. - this.getSite().setSelectionProvider(this.viewer); - - // Add a DoubleClickListener - this.addDoubleClickAction(); - - // TODO: verify XML - // Fill tree with values from xml - // this.fillView(); - - // Layout the viewer - final GridData gridData = new GridData(); - gridData.verticalAlignment = GridData.FILL; - gridData.horizontalSpan = this.titles.length; - gridData.grabExcessHorizontalSpace = true; - gridData.grabExcessVerticalSpace = true; - gridData.horizontalAlignment = GridData.FILL; - this.viewer.getTree().setLayoutData(gridData); - - LOGGER.finest("End createViewer method"); - } - - /** - * Action to do when a double click over the item is done - */ - protected abstract void addDoubleClickAction(); - - /** - * Fill view with the values from the xml file - */ - protected abstract void fillView(); - - /** - * This method creates all columns of the tree table viewer. - */ - protected abstract void createColumns(); - - /** - * This method creates a tree viewer column. - * - * @param title - * title of the column - * @param bound - * size of the column - * @return a table viewer's column - */ - protected TreeViewerColumn createTreeViewerColumn(final String title, final int bound) { - LOGGER.finest("Begin createTreeViewerColumn method"); - - final TreeViewerColumn viewerColumn = new TreeViewerColumn(this.viewer, SWT.NONE); - final TreeColumn column = viewerColumn.getColumn(); - column.setText(title); - column.setWidth(bound); - column.setResizable(true); - column.setMoveable(false); - - LOGGER.finest("End createTreeViewerColumn method"); - return viewerColumn; - } - - /* - * (non-Javadoc) - * - * @see org.eclipse.ui.part.WorkbenchPart#setFocus() - */ - @Override - public void setFocus() { - this.viewer.getControl().setFocus(); - } - -} diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java index 806612d0..b2922909 100755 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java @@ -30,16 +30,23 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.TreeViewerColumn; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.part.ViewPart; /** * View displaying the metrics computation results. * * @see fr.cnes.analysis.tools.ui.view.AbstractAnalysisView */ -public class MetricsView extends AbstractAnalysisView { +public class MetricsView extends ViewPart { /** * Relative path to the XSD contained in the project for XML analysisResult @@ -51,11 +58,13 @@ public class MetricsView extends AbstractAnalysisView { public static final String VIEW_ID = MetricsView.class.getName(); /** Bounds value. **/ - public static final int[] BOUNDS = { 200, 75, 75, 75, 75, 200, 200 }; + private final int[] bounds = { 200, 75, 75, 75, 75, 200, 200 }; /** Columns titles **/ - public static final String[] TITLES = { "Metric", "Total", "Mean", "Minimum", "Maximum" }; + private final String[] titles = { "Metric", "Total", "Mean", "Minimum", "Maximum" }; + /** The viewer which display results. **/ + private TreeViewer viewer; /** * */ @@ -82,7 +91,7 @@ public class MetricsView extends AbstractAnalysisView { * Empty constructor. */ public MetricsView() { - super(BOUNDS, TITLES); + super(); analysisResult = new TreeSet<>(new Comparator() { @Override @@ -101,9 +110,68 @@ public int compare(final CheckResult value1, final CheckResult value2) { /* * (non-Javadoc) * - * @see fr.cnes.analysis.tools.ui.view.AbstractAnalysisView#createColumns() + * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt. + * widgets .Composite) */ @Override + public void createPartControl(final Composite parent) { + LOGGER.finest("Begin createPartControl method"); + + final GridLayout layout = new GridLayout(this.titles.length, false); + parent.setLayout(layout); + this.createViewer(parent); + + LOGGER.finest("End createPartControl method"); + } + + /** + * This method create the viewer, which is a tree table. + * + * @param parent + * the parent composite + */ + private void createViewer(final Composite parent) { + LOGGER.finest("Begin createViewer method"); + + // Defining overall style for TreeViewer + final int scrollStyle = SWT.H_SCROLL | SWT.V_SCROLL; + final int selecStyle = SWT.MULTI | SWT.FULL_SELECTION; + final int style = scrollStyle | selecStyle; + this.viewer = new TreeViewer(parent, style | SWT.FILL); + // Make headers and lines of the tree visible + final Tree tree = this.viewer.getTree(); + tree.setHeaderVisible(true); + tree.setLinesVisible(true); + + // Setting the content provider and creating columns + this.createColumns(); + + // Expand the tree + this.viewer.setAutoExpandLevel(1); + + // Add selection provider which allows to listen to each + // selection made on this viewer. + this.getSite().setSelectionProvider(this.viewer); + + // Add a DoubleClickListener + this.addDoubleClickAction(); + + // TODO: verify XML + // Fill tree with values from xml + // this.fillView(); + + // Layout the viewer + final GridData gridData = new GridData(); + gridData.verticalAlignment = GridData.FILL; + gridData.horizontalSpan = this.titles.length; + gridData.grabExcessHorizontalSpace = true; + gridData.grabExcessVerticalSpace = true; + gridData.horizontalAlignment = GridData.FILL; + this.viewer.getTree().setLayoutData(gridData); + + LOGGER.finest("End createViewer method"); + } + protected void createColumns() { LOGGER.finest("Begin createColumns method"); @@ -120,14 +188,32 @@ protected void createColumns() { LOGGER.finest("End createColumns method"); } - /* - * (non-Javadoc) + /** + * This method creates a tree viewer column. * - * @see fr.cnes.analysis.tools.ui.view.AbstractAnalysisView# - * addDoubleClickAction () + * @param title + * title of the column + * @param bound + * size of the column + * @return a table viewer's column */ + protected TreeViewerColumn createTreeViewerColumn(final String title, final int bound) { + LOGGER.finest("Begin createTreeViewerColumn method"); + + final TreeViewerColumn viewerColumn = new TreeViewerColumn(this.viewer, SWT.NONE); + final TreeColumn column = viewerColumn.getColumn(); + column.setText(title); + column.setWidth(bound); + column.setResizable(true); + column.setMoveable(false); + + LOGGER.finest("End createTreeViewerColumn method"); + return viewerColumn; + } - @Override + /** + * Action to do when a double click over the item is done + */ protected void addDoubleClickAction() { LOGGER.finest("begin method addDoubleClickAction"); final TreeViewer viewer = this.getViewer(); @@ -306,22 +392,53 @@ public void clear() throws EmptyProviderException { this.getViewer().refresh(); } - /* - * (non-Javadoc) + /** + * @return the analysisResult + */ + public final Set getAnalysisResult() { + return analysisResult; + } + + /** + * Getter for the bounds. * - * @see fr.cnes.analysis.tools.ui.view.AbstractAnalysisView#fillView() + * @return the bounds */ - @Override - protected void fillView() { - // TODO not implemented yet + public int[] getBounds() { + return this.bounds.clone(); + } + /** + * Getter for the titles. + * + * @return the titles + */ + public String[] getTitles() { + return this.titles.clone(); } /** - * @return the analysisResult + * Getter for the viewer. + * + * @return the viewer */ - public final Set getAnalysisResult() { - return analysisResult; + public TreeViewer getViewer() { + return this.viewer; + } + + /** + * Setter for the viewer. + * + * @param pViewer + * this.descriptors.clone() set + */ + public void setViewer(final TreeViewer pViewer) { + this.viewer = pViewer; + } + + @Override + public void setFocus() { + this.viewer.getControl().setFocus(); } } From a56fb00831fa4ec1ad211fe21e38c55bea8faeeb Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Thu, 6 Jul 2017 18:05:17 +0200 Subject: [PATCH 09/15] Fix #44 Directly calling viewer instead of it's getter. --- .../analysis/tools/ui/view/MetricsView.java | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java index b2922909..c95e5865 100755 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/view/MetricsView.java @@ -66,7 +66,6 @@ public class MetricsView extends ViewPart { /** The viewer which display results. **/ private TreeViewer viewer; /** - * */ public static final List MARKERS = new ArrayList(); @@ -156,10 +155,6 @@ private void createViewer(final Composite parent) { // Add a DoubleClickListener this.addDoubleClickAction(); - // TODO: verify XML - // Fill tree with values from xml - // this.fillView(); - // Layout the viewer final GridData gridData = new GridData(); gridData.verticalAlignment = GridData.FILL; @@ -175,7 +170,7 @@ private void createViewer(final Composite parent) { protected void createColumns() { LOGGER.finest("Begin createColumns method"); - this.getViewer().setContentProvider(new MetricContentProvider()); + viewer.setContentProvider(new MetricContentProvider()); TreeViewerColumn col; for (int i = 0; i < this.getTitles().length; i++) { // Create the column @@ -216,20 +211,18 @@ protected TreeViewerColumn createTreeViewerColumn(final String title, final int */ protected void addDoubleClickAction() { LOGGER.finest("begin method addDoubleClickAction"); - final TreeViewer viewer = this.getViewer(); viewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(final DoubleClickEvent event) { - final TreeViewer tViewer = (TreeViewer) event.getViewer(); final IStructuredSelection thisSelection = (IStructuredSelection) event .getSelection(); final Object selectedNode = thisSelection.getFirstElement(); - tViewer.setExpandedState(selectedNode, !tViewer.getExpandedState(selectedNode)); + viewer.setExpandedState(selectedNode, !viewer.getExpandedState(selectedNode)); // if it is a leaf -> open the file - if (!tViewer.isExpandable(selectedNode) + if (!viewer.isExpandable(selectedNode) && selectedNode instanceof FunctionMetricDescriptor) { // get Path of the file & Line of the @@ -362,8 +355,8 @@ public int compare(final CheckResult value1, final CheckResult value2) { } }); - if (this.getViewer().getInput() != null) { - for (final CheckResult input : (CheckResult[]) this.getViewer().getInput()) { + if (viewer.getInput() != null) { + for (final CheckResult input : (CheckResult[]) viewer.getInput()) { listInputs.add(input); } } @@ -372,10 +365,10 @@ public int compare(final CheckResult value1, final CheckResult value2) { listInputs.add(value); } analysisResult = listInputs; - this.getViewer().setInput(listInputs.toArray(new CheckResult[listInputs.size()])); + viewer.setInput(listInputs.toArray(new CheckResult[listInputs.size()])); } - this.getViewer().refresh(); + viewer.refresh(); LOGGER.finest("End display method"); } @@ -388,8 +381,8 @@ public int compare(final CheckResult value1, final CheckResult value2) { */ public void clear() throws EmptyProviderException { this.analysisResult.clear(); - this.getViewer().setInput(new CheckResult[0]); - this.getViewer().refresh(); + viewer.setInput(new CheckResult[0]); + viewer.refresh(); } /** From d2135f39b9d991f699e42822ea91bbe6d308cd1b Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Thu, 6 Jul 2017 18:19:38 +0200 Subject: [PATCH 10/15] Fix #39 Editing command ids and message to be more informative --- fr.cnes.analysis.tools.ui/plugin.xml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/fr.cnes.analysis.tools.ui/plugin.xml b/fr.cnes.analysis.tools.ui/plugin.xml index 6bccf474..90bce777 100755 --- a/fr.cnes.analysis.tools.ui/plugin.xml +++ b/fr.cnes.analysis.tools.ui/plugin.xml @@ -17,10 +17,11 @@ - + style="push" + tooltip="Running an i-Code CNES analysis on selected files."> + commandId="fr.cnes.analysis.tools.all.ui.handler.AnalysisHandler" + helpContextId="Running an i-Code CNES analysis on selected files."> From e6eb05ca100678e2c12a93597a9ccfa51db1879f Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Fri, 7 Jul 2017 13:35:17 +0200 Subject: [PATCH 11/15] Fix #55 Preferences page enable and disable checkbox improvement --- .../CheckerPreferencesContainer.java | 32 ++++++++++ .../ConfigurationPreferencePage.java | 25 +++++--- .../checkerstables/CheckerTableViewer.java | 59 +++++++++++++++---- 3 files changed, 97 insertions(+), 19 deletions(-) diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/CheckerPreferencesContainer.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/CheckerPreferencesContainer.java index 7b71e69f..19688802 100644 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/CheckerPreferencesContainer.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/CheckerPreferencesContainer.java @@ -150,16 +150,48 @@ public void savePreferences() { public void setToDefault() { final IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + this.checked = store.getDefaultBoolean(this.getId()); store.setToDefault(this.getId()); + this.severity = store + .getDefaultString(this.getId() + UserPreferencesService.PREF_SEVERITY_KEY); store.setToDefault(this.getId() + UserPreferencesService.PREF_SEVERITY_KEY); + if (this.isMetric) { + this.maxValue = store + .getDefaultFloat(this.getId() + UserPreferencesService.PREF_MAX_VALUE_KEY); store.setToDefault(this.getId() + UserPreferencesService.PREF_MAX_VALUE_KEY); } if (this.isMetric) { + this.minValue = store + .getDefaultFloat(this.getId() + UserPreferencesService.PREF_MAX_VALUE_KEY); store.setToDefault(this.getId() + UserPreferencesService.PREF_MIN_VALUE_KEY); } } + public void update() { + final IPreferenceStore store = Activator.getDefault().getPreferenceStore(); + if (!store.contains(this.getId())) { + this.checked = true; + } else { + this.checked = store.getBoolean(this.getId()); + } + if (!store.contains(this.getId() + UserPreferencesService.PREF_SEVERITY_KEY)) { + this.severity = UserPreferencesService.PREF_SEVERITY_ERROR_VALUE; + } else { + this.severity = store + .getString(this.getId() + UserPreferencesService.PREF_SEVERITY_KEY); + } + + if (this.isMetric) { + this.maxValue = store + .getFloat(this.getId() + UserPreferencesService.PREF_MAX_VALUE_KEY); + } + if (this.isMetric) { + this.minValue = store + .getFloat(this.getId() + UserPreferencesService.PREF_MIN_VALUE_KEY); + } + } + /** * @return the isMetric */ diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/ConfigurationPreferencePage.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/ConfigurationPreferencePage.java index 53942c59..d2d1ec47 100644 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/ConfigurationPreferencePage.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/ConfigurationPreferencePage.java @@ -27,7 +27,6 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; -import org.eclipse.ui.plugin.AbstractUIPlugin; public class ConfigurationPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { @@ -158,11 +157,13 @@ public int compare(CheckerPreferencesContainer arg0, public void widgetSelected(SelectionEvent e) { configurationId = configurationSelection .getItem(configurationSelection.getSelectionIndex()); + refresh(); } }); parent.getParent().pack(); parent.getParent().redraw(); + this.refresh(); return composite; } @@ -182,15 +183,24 @@ public void performApply() { checker.savePreferences(); } } else { - - try - - { + for (CheckerPreferencesContainer checker : checkersMetricTable.getInputs()) { + checker.setToDefault(); + } + for (CheckerPreferencesContainer checker : checkersTable.getInputs()) { + checker.setToDefault(); + } + try { UserPreferencesService.setConfiguration(configurationId); } catch (NullContributionException e) { // TODO Auto-generated catch block e.printStackTrace(); } + for (CheckerPreferencesContainer checker : checkersMetricTable.getInputs()) { + checker.update(); + } + for (CheckerPreferencesContainer checker : checkersTable.getInputs()) { + checker.update(); + } } this.refresh(); } @@ -230,9 +240,10 @@ public boolean performOk() { * Redraw every elements of the view. */ public void refresh() { + this.composite.getParent().getParent().redraw(); + this.composite.layout(); + this.composite.redraw(); checkersMetricTable.refresh(); checkersTable.refresh(); - this.composite.redraw(); - } } diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/checkerstables/CheckerTableViewer.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/checkerstables/CheckerTableViewer.java index d7f0d5e3..a31b8f84 100644 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/checkerstables/CheckerTableViewer.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/preferences/checkerstables/CheckerTableViewer.java @@ -115,6 +115,7 @@ public Image getImage(Object element) { } else { image = disabledImage; } + return image; } }); @@ -188,39 +189,74 @@ protected TableViewerColumn createEnabledViewerColumn(int bound, final int colNu column.setImage(ImageFactory.getImage(ImageFactory.DISABLED)); column.setToolTipText("Check to select or unselect every rules in the table."); column.setWidth(bound); - allEnabledChecked = false; column.setResizable(true); column.setMoveable(true); enableAllListerner = new Listener() { @Override public void handleEvent(Event event) { + /* + * If the event is a selection one, then we have to set inputs + * to get all of them checked or unchecked. + */ + if (event.type == SWT.Selection) { + if (UserPreferencesService.isDefaultConfigurationActive()) { + if (!allEnabledChecked) { + column.setImage(ImageFactory.getImage(ImageFactory.ENABLED)); + for (CheckerPreferencesContainer checker : inputs) { + checker.setChecked(true); + } + allEnabledChecked = true; + } else { + column.setImage(ImageFactory.getImage(ImageFactory.DISABLED)); + for (CheckerPreferencesContainer checker : inputs) { + checker.setChecked(false); + } + allEnabledChecked = false; + } + } else { + column.setImage(null); + } + } + /* + * Image must be set pending the inputs and the configuration. + */ if (UserPreferencesService.isDefaultConfigurationActive()) { - if (!allEnabledChecked) { + allEnabledChecked = isAllEnabled(); + if (allEnabledChecked) { column.setImage(ImageFactory.getImage(ImageFactory.ENABLED)); - for (CheckerPreferencesContainer checker : inputs) { - checker.setChecked(true); - } - allEnabledChecked = true; } else { column.setImage(ImageFactory.getImage(ImageFactory.DISABLED)); - for (CheckerPreferencesContainer checker : inputs) { - checker.setChecked(false); - } - allEnabledChecked = false; } } else { column.setImage(null); } - refresh(); + + checkersTableViewer.refresh(); + } + + private boolean isAllEnabled() { + int i = 0; + boolean allEnabled = true; + while (i < inputs.size() && allEnabled) { + if (!inputs.get(i).isChecked()) { + allEnabled = false; + } + i++; + } + return allEnabled; } }; column.addListener(SWT.Selection, enableAllListerner); + this.refresh(); return viewerColumn; + } public void refresh() { + this.checkersTableViewer.getControl().redraw(); + this.enableAllListerner.handleEvent(new Event()); this.checkersTableViewer.refresh(); } @@ -258,7 +294,6 @@ public void setAllEnabledChecker(boolean isEnabled) { if (allEnabledChecked && !isEnabled) { allEnabledChecked = false; enabledColumn.getColumn().setImage(disabledImage); - this.refresh(); } } } From b226443fb74a742f95249f6e06753361c3a08549 Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Fri, 7 Jul 2017 14:09:34 +0200 Subject: [PATCH 12/15] Fix #42 Making exception's message more convenient to the user. --- .../src/fr/cnes/analysis/tools/ui/handler/AnalysisHandler.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/handler/AnalysisHandler.java b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/handler/AnalysisHandler.java index 4a450759..ead8defd 100644 --- a/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/handler/AnalysisHandler.java +++ b/fr.cnes.analysis.tools.ui/src/fr/cnes/analysis/tools/ui/handler/AnalysisHandler.java @@ -167,7 +167,8 @@ private List retrieveSelectedFiles(IStructuredSelection pSelection) final List files = new ArrayList<>(); final Iterator selectionIterator = pSelection.iterator(); if (!selectionIterator.hasNext()) { - throw new EmptySelectionException("Erreur d'exécution (EmptySelectionException)."); + throw new EmptySelectionException( + "i-Code CNES : Please select file(s) in the Project Explorer before running an analysis."); } while (selectionIterator.hasNext()) { final IResource selection = selectionIterator.next(); From fefce1fc2739a7a22e0e1e33e9d26ac490d374e8 Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Tue, 11 Jul 2017 14:13:23 +0200 Subject: [PATCH 13/15] Update #30 Add of SH.MET.ComplexitySimplified --- .../lex/SHMETComplexitySimplified.lex | 510 +++++++++++++++--- .../metrics/FunctionComplexitySimplified.java | 45 ++ .../tools/shell/metrics/ShellUtils.java | 28 + 3 files changed, 520 insertions(+), 63 deletions(-) create mode 100644 fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionComplexitySimplified.java create mode 100644 fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/ShellUtils.java diff --git a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETComplexitySimplified.lex b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETComplexitySimplified.lex index 940fe06d..55f98fb5 100755 --- a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETComplexitySimplified.lex +++ b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETComplexitySimplified.lex @@ -15,18 +15,21 @@ package fr.cnes.analysis.tools.shell.metrics; +import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; +import fr.cnes.analysis.tools.analyzer.datas.CheckResult; +import fr.cnes.analysis.tools.analyzer.exception.JFlexException; + +import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; -import java.io.File; -import java.util.LinkedList; + +import java.util.EmptyStackException; import java.util.List; +import java.util.Stack; +import java.util.logging.Logger; import org.eclipse.core.runtime.Path; -import fr.cnes.analysis.tools.analyzer.datas.AbstractChecker; -import fr.cnes.analysis.tools.analyzer.datas.CheckResult; -import fr.cnes.analysis.tools.analyzer.exception.JFlexException; - %% %class SHMETComplexitySimplified @@ -40,28 +43,41 @@ import fr.cnes.analysis.tools.analyzer.exception.JFlexException; %yylexthrow JFlexException %type List -%state COMMENT, NAMING, FUNCTION - -COMMENT_WORD = \# -FUNCTION = "function" -FUNCT = {VAR}{SPACE}*\(\) -SPACE = [\ \r\t\f] -VAR = [a-zA-Z][a-zA-Z0-9\_]* -STRING = \'[^\']*\' | \"[^\"]*\" - -CYCLO = "while" | "for" | "until" | - "if" | "case" | "else" | - "elif" +%state COMMENT, NAMING, BEGINFUNC, STRING_DOUBLE, STRING_SIMPLE, COMMAND, CASE +COMMENT_WORD = [\#] +FUNCT = {FNAME}{SPACE}*[\(]{SPACE}*[\)] +FUNCTION = "function" +FNAME = [a-zA-Z0-9\.\!\-\_\@\?\+]+ +SPACE = [\ \r\t\f\space] +NAME = [a-zA-Z\_][a-zA-Z0-9\_]* +SHELL_VAR = ([0-9]+|[\-\@\?\#\!\_\*\$]) +EXPANDED_VAR = [\$][\{](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\:\%\=\+\?\/\!\-\,\^\#\*\@]|([\[](([\:]{SPACE}*[\-])|[a-zA-Z0-9\_\/\:\%\=\+\?\!\$\-\,\^\#\*\@\[\]\{\}])+[\]]))+[\}] +VAR = {NAME}|{EXPANDED_VAR}|([\$]({NAME}|{SHELL_VAR})) +IGNORE_COMMAND = [\\][\`] +COMMAND = [\`]|([\$][\(]) +END_COMMAND = [\`]|[\)] +STRING_D = \" +IGNORE_STRING_D = [\\][\"] +STRING_S = \' +IGNORE_STRING_S = [\\][\'] +IGNORE = {IGNORE_STRING_D} | {IGNORE_STRING_S} | {IGNORE_COMMAND} +FUNCSTART = \{ | \( | \(\( | \[\[ | "if" | "select" | "for" | "while" | "until" +FUNCEND = \} | \) | \)\) | \]\] | "fi" | "done" +COMPLEX = "else" | "elif" +CASE = "case" +ESAC = "esac" +CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*))*[^\(\)][\)] %{ String location = "MAIN PROGRAM"; - List identifiers = new LinkedList(); - float numCyclo = 0; - float numMaxCyclo = 0; - float numCycloTotal = 0; - int brackets = 0; + private Stack functionStack = new Stack<>(); + float mainComplexity = 1; + float totalComplexity = 0; + int caseState = 0; int functionLine = 0; + Stack commandClosureStack = new Stack<>(); + private static final Logger LOGGER = Logger.getLogger(SHMETComplexitySimplified.class.getName()); public SHMETComplexitySimplified(){ @@ -73,23 +89,26 @@ CYCLO = "while" | "for" | "until" | this.zzReader = new FileReader(new Path(file.getAbsolutePath()).toOSString()); } - private void addImbrics() { - numCyclo++; - if(numMaxCyclo < numCyclo) { - numMaxCyclo = numCyclo; - numCycloTotal = numCyclo; - } - } private void endLocation() throws JFlexException { - this.computeMetric(this.location, numMaxCyclo+1, functionLine+1); + LOGGER.info("begin method endLocation"); + try{ + FunctionComplexitySimplified functionFinished = functionStack.pop(); + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] computing function :"+functionFinished.getName()+" line :"+ functionFinished.getBeginLine()+" with value : "+functionFinished.getComplexity()); + totalComplexity+=functionFinished.getComplexity(); + this.computeMetric(functionFinished.getName(), functionFinished.getComplexity(), functionFinished.getBeginLine()); + }catch(EmptyStackException e){ + String errorMessage = "Class"+this.getClass().getName()+"\n"+e.getMessage()+"\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; + throw new JFlexException(new Exception(errorMessage)); + } + LOGGER.info("end method endLocation"); } %} %eofval{ - this.computeMetric("MAIN PROGRAM", numMaxCyclo+1, 0); - this.computeMetric(null, Float.NaN, 0); + this.computeMetric("MAIN PROGRAM", mainComplexity, 0); + this.computeMetric(null, mainComplexity+totalComplexity, 0); return getCheckResults(); %eofval} %% @@ -103,49 +122,414 @@ CYCLO = "while" | "for" | "until" | /************************/ { - \n {yybegin(YYINITIAL);} - . {} + \n { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMENT -> YYINITIAL (Transition : \\n )"); + yybegin(YYINITIAL); + } + . | {SPACE} { + LOGGER.fine("Do nothing"); + } + } + +/************************/ +/* YYINITIAL STATE */ +/************************/ + + { + {COMMENT_WORD} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); + yybegin(COMMENT); + } + + {FUNCTION} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); + yybegin(NAMING); + } + + {FUNCT} { + functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); + functionStack.peek().addStarterRepetition(); + } + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity for FUNCSTART \""+yytext()+"\" )"); + functionStack.peek().addComplexity(FunctionComplexitySimplified.computeComplexity(yytext())); + } else { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity for main function with FUNCSTART \""+yytext()+"\" )"); + mainComplexity += FunctionComplexitySimplified.computeComplexity(yytext()); + } + + } + + {COMPLEX} { + if(functionStack.empty()){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the main function"); + mainComplexity += FunctionComplexitySimplified.computeComplexity(yytext()); + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the function "+functionStack.peek().getName()+"."); + functionStack.peek().addComplexity(FunctionComplexitySimplified.computeComplexity(yytext())); + } + } + {CASE} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] increasing case number to "+caseState+" for CASE \""+yytext()+"\" ."); + caseState++; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STATE (Transition : CASE \""+yytext()+"\" )"); + yybegin(CASE); + } + + + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); + functionStack.peek().removeStarterRepetition(); + } else { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] endLocation() for FUNCEND \""+yytext()+"\" )"); + endLocation(); + } + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] Do nothing for FUNCEND \""+yytext()+"\" )"); + } + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] Do nothing for FUNCEND \""+yytext()+"\" )"); + } + } + {IGNORE} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); + } + {STRING_D} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_DOUBLE (Transition : STRING_D \""+yytext()+"\" )"); + yybegin(STRING_DOUBLE); + } + {STRING_S} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_SIMPLE (Transition : STRING_S \""+yytext()+"\" )"); + yybegin(STRING_SIMPLE); + } + {COMMAND} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); + commandClosureStack.push(ShellUtils.commandClosure(yytext())); + yybegin(COMMAND); + } + + + {VAR} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); + } + + + + \n | {SPACE} | . { + LOGGER.fine("Do nothing"); + } + } +/************************/ +/* CASE STATE */ +/************************/ + + { + + {COMMENT_WORD} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); + yybegin(COMMENT); + } + + {FUNCTION} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); + yybegin(NAMING); + } + + {FUNCT} { + functionLine = yyline+1; + location = yytext().substring(0,yytext().length()-2).trim(); + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + + {FUNCSTART} { + if(!functionStack.empty()){ + if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); + functionStack.peek().addStarterRepetition(); + } + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity for FUNCSTART \""+yytext()+"\" )"); + functionStack.peek().addComplexity(FunctionComplexitySimplified.computeComplexity(yytext())); + } else { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity for main function with FUNCSTART \""+yytext()+"\" )"); + mainComplexity += FunctionComplexitySimplified.computeComplexity(yytext()); + } + + } + + {COMPLEX} { + if(functionStack.empty()){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the main function"); + mainComplexity += FunctionComplexitySimplified.computeComplexity(yytext()); + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the function "+functionStack.peek().getName()+"."); + functionStack.peek().addComplexity(FunctionComplexitySimplified.computeComplexity(yytext())); + } + } + + {CASE} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] increasing case number to "+caseState+" for CASE \""+yytext()+"\" ."); + caseState++; + } + {ESAC} { + if(caseState > 0){ + caseState--; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] decreasing case number to "+caseState+" for CASE \""+yytext()+"\" ."); + + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] removeStarterRepetition() for ESAC \""+yytext()+"\" )"); + functionStack.peek().removeStarterRepetition(); + } else { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Running endLocation() for ESAC \""+yytext()+"\" )"); + endLocation(); + } + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Case ending is not closing a function for ESAC : \""+yytext()+"\" "); + } + } + if(caseState==0){ + yybegin(YYINITIAL); + } + }else{ + String errorMessage = "Class: "+this.getClass().getName()+"\nImpossible to handle case closure ESAC because no case has been declared.\nFile :"+ this.getInputFile().getAbsolutePath() +"\nat line:"+yyline+" column:"+yycolumn+"\nLast word read : "+yytext(); + throw new JFlexException(new Exception(errorMessage)); + } + } + {CASE_STATEMENT} { + if(caseState>0){ + if(functionStack.empty()){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Compute case statement for main function with CASE_STATEMENT \""+yytext()+"\"."); + mainComplexity++; + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Compute case statement for "+functionStack.peek().getName()+" for CASE_STATEMENT \""+yytext()+"\"."); + functionStack.peek().computeCase(); + } + }else{ + String errorMessage = "Class: "+this.getClass().getName()+"\nHandling CASE_STATEMENT while no case were declared.\nFile :"+ this.getInputFile().getAbsolutePath() +"\nat line:"+yyline+" column:"+yycolumn+"\nLast word read : "+yytext(); + throw new JFlexException(new Exception(errorMessage)); + } + } + {FUNCEND} { + if(!functionStack.empty()){ + if(functionStack.peek().isFinisher(yytext())){ + if(functionStack.peek().getStarterRepetition()>0) { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); + functionStack.peek().removeStarterRepetition(); + } else { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] endLocation() for FUNCEND \""+yytext()+"\" )"); + endLocation(); + } + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Do nothing for FUNCEND \""+yytext()+"\" )"); + } + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Do nothing for FUNCEND \""+yytext()+"\" )"); + } + } + {IGNORE} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] do nothing for IGNORE \""+yytext()+"\" )"); + } + {STRING_D} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> STRING_DOUBLE (Transition : STRING_D \""+yytext()+"\" )"); + yybegin(STRING_DOUBLE); + } + {STRING_S} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> STRING_SIMPLE (Transition : STRING_S \""+yytext()+"\" )"); + yybegin(STRING_SIMPLE); + } + {COMMAND} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); + commandClosureStack.push(ShellUtils.commandClosure(yytext())); + yybegin(COMMAND); + } + + + {VAR} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] do nothing for IGNORE \""+yytext()+"\" )"); + } + + + + \n | {SPACE} | . { + LOGGER.fine("Do nothing"); + } + } +/************************/ +/* STRING_SIMPLE STATE */ +/************************/ + + { + {IGNORE} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING_SIMPLE] do nothing for IGNORE \""+yytext()+"\" )"); + } + {STRING_S} { + if(commandClosureStack.empty()){ + if(caseState==0){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_SIMPLE -> YYINITIAL (Transition STRING_S : \""+yytext()+"\" )"); + yybegin(YYINITIAL); + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_SIMPLE -> CASE (Transition STRING_S : \""+yytext()+"\" )"); + yybegin(CASE); + } + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_SIMPLE -> COMMAND (Transition STRING_S : \""+yytext()+"\" )"); + yybegin(COMMAND); + } + } + . | {SPACE} | \n { + LOGGER.fine("Do nothing"); + } + } +/************************/ +/* STRING_DOUBLE STATE */ +/************************/ + + { + {IGNORE} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING_DOUBLE] do nothing for IGNORE \""+yytext()+"\" )"); + + } + {STRING_D} { + if(commandClosureStack.empty()){ + if(caseState==0){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_DOUBLE -> YYINITIAL (Transition STRING_D : \""+yytext()+"\" )"); + yybegin(YYINITIAL); + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_DOUBLE -> CASE (Transition STRING_D : \""+yytext()+"\" )"); + yybegin(CASE); + } + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_DOUBLE -> COMMAND (Transition STRING_D : \""+yytext()+"\" )"); + yybegin(COMMAND); + } + } + . | {SPACE} | \n { + LOGGER.fine("Do nothing"); + } + } +/************************/ +/* COMMAND STATE */ +/************************/ + + { + {IGNORE} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [COMMAND] do nothing for IGNORE \""+yytext()+"\" )"); + + } + {STRING_D} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_DOUBLE (Transition : STRING_D \""+yytext()+"\" )"); + yybegin(STRING_DOUBLE); + } + {STRING_S} { + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_SIMPLE (Transition : STRING_S \""+yytext()+"\" )"); + yybegin(STRING_SIMPLE); + } + {FUNCT} {} + {FUNCSTART} {} + {VAR} {} + {END_COMMAND} { + if(yytext().equals(commandClosureStack.peek())){ + + commandClosureStack.pop(); + if(commandClosureStack.empty()){ + if(caseState==0){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> YYINITIAL (Transition COMMAND : \""+yytext()+"\" )"); + yybegin(YYINITIAL); + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> CASE (Transition COMMAND : \""+yytext()+"\" )"); + yybegin(CASE); + } + } + }else{ + //Do nothing + } + } + . | {SPACE} | \n { + LOGGER.fine("Do nothing"); + } } - - /************************/ /* NAMING STATE */ /************************/ { - {VAR} {functionLine=yyline;location = yytext(); yybegin(YYINITIAL);} - \n {yybegin(YYINITIAL);} - . {} + {VAR} { + location = yytext(); + functionLine = yyline+1; + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> BEGINFUNC (Transition : VAR \""+yytext()+"\" )"); + yybegin(BEGINFUNC); + } + \n { + if(caseState==0){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : \\n )"); + yybegin(YYINITIAL); + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> CASE (Transition : \\n )"); + yybegin(CASE); + } + } + . | {SPACE} { + LOGGER.fine("Do nothing"); + } } /************************/ -/* YYINITIAL STATE */ +/* BEGINFUNC STATE */ /************************/ - +/* + * This state target is to retrieve the function starter. For more information on fonction starter, have a look on {@link Function} class. + * Pending this starter, the function ender can be defined. + * + */ + { - {COMMENT_WORD} {yybegin(COMMENT);} - {FUNCTION} {yybegin(NAMING);} - {FUNCT} {functionLine=yyline;location = yytext().substring(0,yytext().length()-2).trim(); } - {STRING} {} - {CYCLO} {addImbrics();} - {VAR}(\=)? {} - \{ (\#)? {brackets++;} - \} {brackets--; - if(brackets==0 && !location.equals("MAIN PROGRAM")) { - endLocation(); - functionLine=0; - location = "MAIN PROGRAM"; - numMaxCyclo=0; - numCyclo=0; - }} - [^] {} + \(\) { + LOGGER.fine("Do nothing"); + } + {FUNCSTART} { + FunctionComplexitySimplified function; + function = new FunctionComplexitySimplified(location, functionLine, yytext()); + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for FUNCSTART \""+yytext()+"\" )"); + functionStack.push(function); + if(caseState==0){ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> YYINITIAL (Transition : FUNCSTART \""+yytext()+"\" )"); + yybegin(YYINITIAL); + }else{ + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> CASE (Transition : FUNCSTART \""+yytext()+"\" )"); + yybegin(CASE); + } + } + {CASE} { + caseState++; + FunctionComplexitySimplified function; + function = new FunctionComplexitySimplified(location, functionLine, yytext()); + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for CASE \""+yytext()+"\" )"); + functionStack.push(function); + LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> CASE (Transition : CASE \""+yytext()+"\" )"); + yybegin(CASE); + } + . |{SPACE} | \n { + LOGGER.fine("Do nothing"); + } } - - - /************************/ /* ERROR STATE */ /************************/ - [^] {} - + [^] { + String errorMessage = "Class: "+this.getClass().getName()+"\nIllegal character <" + yytext() + ">\nFile :"+ this.getInputFile().getAbsolutePath() +"\nat line:"+yyline+" column:"+yycolumn+"\nLast word read : "+yytext(); + throw new JFlexException(new Exception(errorMessage)); + } \ No newline at end of file diff --git a/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionComplexitySimplified.java b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionComplexitySimplified.java new file mode 100644 index 00000000..e7d6938d --- /dev/null +++ b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/FunctionComplexitySimplified.java @@ -0,0 +1,45 @@ +package fr.cnes.analysis.tools.shell.metrics; + +public class FunctionComplexitySimplified extends Function { + + private float complexity; + + public FunctionComplexitySimplified(String pName, int pBeginLine, String pStarter) { + super(pName, pBeginLine, pStarter); + this.complexity = 1; + this.complexity += computeComplexity(pStarter); + } + + public static float computeComplexity(String pStarter) { + float complexity; + switch (pStarter) { + case "while": + case "for": + case "until": + complexity = 2; + break; + case "if": + case "else": + case "elif": + complexity = 1; + break; + default: + complexity = 0; + } + return complexity; + + } + + public void computeCase() { + this.complexity++; + } + + public void addComplexity(float complexity) { + this.complexity += complexity; + } + + public float getComplexity() { + return this.complexity; + } + +} diff --git a/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/ShellUtils.java b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/ShellUtils.java new file mode 100644 index 00000000..336288d5 --- /dev/null +++ b/fr.cnes.analysis.tools.shell.metrics/src/fr/cnes/analysis/tools/shell/metrics/ShellUtils.java @@ -0,0 +1,28 @@ +/** + * + */ +package fr.cnes.analysis.tools.shell.metrics; + +/** + * @author waldmao + * + */ +public final class ShellUtils { + + public static String commandClosure(String commandOpening) { + String closure = null; + switch (commandOpening) { + case "`": + closure = "`"; + break; + case "$(": + closure = ")"; + break; + default: + closure = null; + break; + } + return closure; + } + +} From 042192032f220d43b88714fc76b1d27f63f76094 Mon Sep 17 00:00:00 2001 From: Omar WALDMANN Date: Tue, 11 Jul 2017 14:20:33 +0200 Subject: [PATCH 14/15] Fix #30 Logger level decreased to fine. --- .../lex/SHMETComplexitySimplified.lex | 136 +++++++++--------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETComplexitySimplified.lex b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETComplexitySimplified.lex index 55f98fb5..43eb0fbd 100755 --- a/fr.cnes.analysis.tools.shell.metrics/lex/SHMETComplexitySimplified.lex +++ b/fr.cnes.analysis.tools.shell.metrics/lex/SHMETComplexitySimplified.lex @@ -91,17 +91,17 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s private void endLocation() throws JFlexException { - LOGGER.info("begin method endLocation"); + LOGGER.fine("begin method endLocation"); try{ FunctionComplexitySimplified functionFinished = functionStack.pop(); - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] computing function :"+functionFinished.getName()+" line :"+ functionFinished.getBeginLine()+" with value : "+functionFinished.getComplexity()); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] computing function :"+functionFinished.getName()+" line :"+ functionFinished.getBeginLine()+" with value : "+functionFinished.getComplexity()); totalComplexity+=functionFinished.getComplexity(); this.computeMetric(functionFinished.getName(), functionFinished.getComplexity(), functionFinished.getBeginLine()); }catch(EmptyStackException e){ String errorMessage = "Class"+this.getClass().getName()+"\n"+e.getMessage()+"\nFile :"+ this.getInputFile().getAbsolutePath() + "\nat line:"+yyline+" column:"+yycolumn; throw new JFlexException(new Exception(errorMessage)); } - LOGGER.info("end method endLocation"); + LOGGER.fine("end method endLocation"); } %} @@ -123,7 +123,7 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s { \n { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMENT -> YYINITIAL (Transition : \\n )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMENT -> YYINITIAL (Transition : \\n )"); yybegin(YYINITIAL); } . | {SPACE} { @@ -137,32 +137,32 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s { {COMMENT_WORD} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); yybegin(COMMENT); } {FUNCTION} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); yybegin(NAMING); } {FUNCT} { functionLine = yyline+1; location = yytext().substring(0,yytext().length()-2).trim(); - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); yybegin(BEGINFUNC); } {FUNCSTART} { if(!functionStack.empty()){ if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); functionStack.peek().addStarterRepetition(); } - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity for FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity for FUNCSTART \""+yytext()+"\" )"); functionStack.peek().addComplexity(FunctionComplexitySimplified.computeComplexity(yytext())); } else { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity for main function with FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity for main function with FUNCSTART \""+yytext()+"\" )"); mainComplexity += FunctionComplexitySimplified.computeComplexity(yytext()); } @@ -170,17 +170,17 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s {COMPLEX} { if(functionStack.empty()){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the main function"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the main function"); mainComplexity += FunctionComplexitySimplified.computeComplexity(yytext()); }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the function "+functionStack.peek().getName()+"."); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the function "+functionStack.peek().getName()+"."); functionStack.peek().addComplexity(FunctionComplexitySimplified.computeComplexity(yytext())); } } {CASE} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] increasing case number to "+caseState+" for CASE \""+yytext()+"\" ."); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] increasing case number to "+caseState+" for CASE \""+yytext()+"\" ."); caseState++; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STATE (Transition : CASE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STATE (Transition : CASE \""+yytext()+"\" )"); yybegin(CASE); } @@ -189,39 +189,39 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s if(!functionStack.empty()){ if(functionStack.peek().isFinisher(yytext())){ if(functionStack.peek().getStarterRepetition()>0) { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); functionStack.peek().removeStarterRepetition(); } else { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] endLocation() for FUNCEND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] endLocation() for FUNCEND \""+yytext()+"\" )"); endLocation(); } }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] Do nothing for FUNCEND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] Do nothing for FUNCEND \""+yytext()+"\" )"); } }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] Do nothing for FUNCEND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] Do nothing for FUNCEND \""+yytext()+"\" )"); } } {IGNORE} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); } {STRING_D} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_DOUBLE (Transition : STRING_D \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_DOUBLE (Transition : STRING_D \""+yytext()+"\" )"); yybegin(STRING_DOUBLE); } {STRING_S} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_SIMPLE (Transition : STRING_S \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_SIMPLE (Transition : STRING_S \""+yytext()+"\" )"); yybegin(STRING_SIMPLE); } {COMMAND} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); commandClosureStack.push(ShellUtils.commandClosure(yytext())); yybegin(COMMAND); } {VAR} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [YYINITIAL] do nothing for IGNORE \""+yytext()+"\" )"); } @@ -237,32 +237,32 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s { {COMMENT_WORD} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> COMMENT (Transition : COMMENT_WORD \""+yytext()+"\" )"); yybegin(COMMENT); } {FUNCTION} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> NAMING (Transition : FUNCTION \""+yytext()+"\" )"); yybegin(NAMING); } {FUNCT} { functionLine = yyline+1; location = yytext().substring(0,yytext().length()-2).trim(); - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> BEGINFUNC (Transition : FUNCT \""+yytext()+"\" )"); yybegin(BEGINFUNC); } {FUNCSTART} { if(!functionStack.empty()){ if(functionStack.peek().getFinisher().equals(Function.finisherOf(yytext()))){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] addStarterRepetition() for FUNCSTART \""+yytext()+"\" )"); functionStack.peek().addStarterRepetition(); } - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity for FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity for FUNCSTART \""+yytext()+"\" )"); functionStack.peek().addComplexity(FunctionComplexitySimplified.computeComplexity(yytext())); } else { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity for main function with FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity for main function with FUNCSTART \""+yytext()+"\" )"); mainComplexity += FunctionComplexitySimplified.computeComplexity(yytext()); } @@ -270,34 +270,34 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s {COMPLEX} { if(functionStack.empty()){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the main function"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the main function"); mainComplexity += FunctionComplexitySimplified.computeComplexity(yytext()); }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the function "+functionStack.peek().getName()+"."); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] computing complexity of OTHER_COMPLEX \""+yytext()+"\" ) for the function "+functionStack.peek().getName()+"."); functionStack.peek().addComplexity(FunctionComplexitySimplified.computeComplexity(yytext())); } } {CASE} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] increasing case number to "+caseState+" for CASE \""+yytext()+"\" ."); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] increasing case number to "+caseState+" for CASE \""+yytext()+"\" ."); caseState++; } {ESAC} { if(caseState > 0){ caseState--; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] decreasing case number to "+caseState+" for CASE \""+yytext()+"\" ."); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] decreasing case number to "+caseState+" for CASE \""+yytext()+"\" ."); if(!functionStack.empty()){ if(functionStack.peek().isFinisher(yytext())){ if(functionStack.peek().getStarterRepetition()>0) { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] removeStarterRepetition() for ESAC \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] removeStarterRepetition() for ESAC \""+yytext()+"\" )"); functionStack.peek().removeStarterRepetition(); } else { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Running endLocation() for ESAC \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Running endLocation() for ESAC \""+yytext()+"\" )"); endLocation(); } }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Case ending is not closing a function for ESAC : \""+yytext()+"\" "); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Case ending is not closing a function for ESAC : \""+yytext()+"\" "); } } if(caseState==0){ @@ -311,10 +311,10 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s {CASE_STATEMENT} { if(caseState>0){ if(functionStack.empty()){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Compute case statement for main function with CASE_STATEMENT \""+yytext()+"\"."); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Compute case statement for main function with CASE_STATEMENT \""+yytext()+"\"."); mainComplexity++; }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Compute case statement for "+functionStack.peek().getName()+" for CASE_STATEMENT \""+yytext()+"\"."); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Compute case statement for "+functionStack.peek().getName()+" for CASE_STATEMENT \""+yytext()+"\"."); functionStack.peek().computeCase(); } }else{ @@ -326,39 +326,39 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s if(!functionStack.empty()){ if(functionStack.peek().isFinisher(yytext())){ if(functionStack.peek().getStarterRepetition()>0) { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] removeStarterRepetition() for FUNCEND \""+yytext()+"\" )"); functionStack.peek().removeStarterRepetition(); } else { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] endLocation() for FUNCEND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] endLocation() for FUNCEND \""+yytext()+"\" )"); endLocation(); } }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Do nothing for FUNCEND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Do nothing for FUNCEND \""+yytext()+"\" )"); } }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Do nothing for FUNCEND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] Do nothing for FUNCEND \""+yytext()+"\" )"); } } {IGNORE} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] do nothing for IGNORE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] do nothing for IGNORE \""+yytext()+"\" )"); } {STRING_D} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> STRING_DOUBLE (Transition : STRING_D \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> STRING_DOUBLE (Transition : STRING_D \""+yytext()+"\" )"); yybegin(STRING_DOUBLE); } {STRING_S} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> STRING_SIMPLE (Transition : STRING_S \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> STRING_SIMPLE (Transition : STRING_S \""+yytext()+"\" )"); yybegin(STRING_SIMPLE); } {COMMAND} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - CASE -> COMMAND (Transition : COMMAND \""+yytext()+"\" )"); commandClosureStack.push(ShellUtils.commandClosure(yytext())); yybegin(COMMAND); } {VAR} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] do nothing for IGNORE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [CASE] do nothing for IGNORE \""+yytext()+"\" )"); } @@ -373,19 +373,19 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s { {IGNORE} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING_SIMPLE] do nothing for IGNORE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING_SIMPLE] do nothing for IGNORE \""+yytext()+"\" )"); } {STRING_S} { if(commandClosureStack.empty()){ if(caseState==0){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_SIMPLE -> YYINITIAL (Transition STRING_S : \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_SIMPLE -> YYINITIAL (Transition STRING_S : \""+yytext()+"\" )"); yybegin(YYINITIAL); }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_SIMPLE -> CASE (Transition STRING_S : \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_SIMPLE -> CASE (Transition STRING_S : \""+yytext()+"\" )"); yybegin(CASE); } }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_SIMPLE -> COMMAND (Transition STRING_S : \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_SIMPLE -> COMMAND (Transition STRING_S : \""+yytext()+"\" )"); yybegin(COMMAND); } } @@ -399,20 +399,20 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s { {IGNORE} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING_DOUBLE] do nothing for IGNORE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [STRING_DOUBLE] do nothing for IGNORE \""+yytext()+"\" )"); } {STRING_D} { if(commandClosureStack.empty()){ if(caseState==0){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_DOUBLE -> YYINITIAL (Transition STRING_D : \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_DOUBLE -> YYINITIAL (Transition STRING_D : \""+yytext()+"\" )"); yybegin(YYINITIAL); }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_DOUBLE -> CASE (Transition STRING_D : \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_DOUBLE -> CASE (Transition STRING_D : \""+yytext()+"\" )"); yybegin(CASE); } }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_DOUBLE -> COMMAND (Transition STRING_D : \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - STRING_DOUBLE -> COMMAND (Transition STRING_D : \""+yytext()+"\" )"); yybegin(COMMAND); } } @@ -426,15 +426,15 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s { {IGNORE} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [COMMAND] do nothing for IGNORE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [COMMAND] do nothing for IGNORE \""+yytext()+"\" )"); } {STRING_D} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_DOUBLE (Transition : STRING_D \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_DOUBLE (Transition : STRING_D \""+yytext()+"\" )"); yybegin(STRING_DOUBLE); } {STRING_S} { - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_SIMPLE (Transition : STRING_S \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - YYINITIAL -> STRING_SIMPLE (Transition : STRING_S \""+yytext()+"\" )"); yybegin(STRING_SIMPLE); } {FUNCT} {} @@ -446,10 +446,10 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s commandClosureStack.pop(); if(commandClosureStack.empty()){ if(caseState==0){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> YYINITIAL (Transition COMMAND : \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> YYINITIAL (Transition COMMAND : \""+yytext()+"\" )"); yybegin(YYINITIAL); }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> CASE (Transition COMMAND : \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - COMMAND -> CASE (Transition COMMAND : \""+yytext()+"\" )"); yybegin(CASE); } } @@ -469,15 +469,15 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s {VAR} { location = yytext(); functionLine = yyline+1; - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> BEGINFUNC (Transition : VAR \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> BEGINFUNC (Transition : VAR \""+yytext()+"\" )"); yybegin(BEGINFUNC); } \n { if(caseState==0){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : \\n )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> YYINITIAL (Transition : \\n )"); yybegin(YYINITIAL); }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> CASE (Transition : \\n )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - NAMING -> CASE (Transition : \\n )"); yybegin(CASE); } } @@ -502,13 +502,13 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s {FUNCSTART} { FunctionComplexitySimplified function; function = new FunctionComplexitySimplified(location, functionLine, yytext()); - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for FUNCSTART \""+yytext()+"\" )"); functionStack.push(function); if(caseState==0){ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> YYINITIAL (Transition : FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> YYINITIAL (Transition : FUNCSTART \""+yytext()+"\" )"); yybegin(YYINITIAL); }else{ - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> CASE (Transition : FUNCSTART \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> CASE (Transition : FUNCSTART \""+yytext()+"\" )"); yybegin(CASE); } } @@ -516,9 +516,9 @@ CASE_STATEMENT = ({SPACE}*([^\space\(\)\n]*|{VAR})+{SPACE}*)([\|]({SPACE}*([^\s caseState++; FunctionComplexitySimplified function; function = new FunctionComplexitySimplified(location, functionLine, yytext()); - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for CASE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - [BEGINFUNC] push("+location+") for CASE \""+yytext()+"\" )"); functionStack.push(function); - LOGGER.info("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> CASE (Transition : CASE \""+yytext()+"\" )"); + LOGGER.fine("["+ this.getInputFile().getAbsolutePath()+":"+(yyline+1)+":"+yycolumn+"] - BEGINFUNC -> CASE (Transition : CASE \""+yytext()+"\" )"); yybegin(CASE); } . |{SPACE} | \n { From b680aebcea516edc112480fac93c34da938abc33 Mon Sep 17 00:00:00 2001 From: waldoFR Date: Thu, 13 Jul 2017 15:48:38 +0200 Subject: [PATCH 15/15] Fix #32 Adding a .project file to make project import more convenient. --- fr.cnes.analysis.tools.languages/.project | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 fr.cnes.analysis.tools.languages/.project diff --git a/fr.cnes.analysis.tools.languages/.project b/fr.cnes.analysis.tools.languages/.project new file mode 100644 index 00000000..bd68138d --- /dev/null +++ b/fr.cnes.analysis.tools.languages/.project @@ -0,0 +1,11 @@ + + + fr.cnes.analysis.tools.shell.languages + + + + + + + +