Issue #3497 refactored syntax check to prevent infinite loop possibility

and apply some sanity

Change-Id: I8118a99729c75fc756313db13654f34087a1e648

Former-commit-id: b080e8ef12dc3223b1676b97bc153f9422657514
This commit is contained in:
Nate Jensen 2014-08-06 11:28:02 -05:00
parent e5af41fa86
commit 389ae22829

View file

@ -236,6 +236,7 @@ import com.raytheon.viz.ui.dialogs.ICloseCallback;
* 09Apr2014 #3005 lvenable Added calls to mark the tabs as not current when the tabs are changed. * 09Apr2014 #3005 lvenable Added calls to mark the tabs as not current when the tabs are changed.
* This will show the tab as updating in the header and data text controls. * This will show the tab as updating in the header and data text controls.
* 07/23/2014 15645 zhao modified checkBasicSyntaxError() * 07/23/2014 15645 zhao modified checkBasicSyntaxError()
* 08/13/2014 3497 njensen Refactored syntax checking to prevent potential infinite loop
* *
* </pre> * </pre>
* *
@ -461,11 +462,6 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
*/ */
private TafRecord[] tafsInViewer; private TafRecord[] tafsInViewer;
/**
* Set to true is Python Syntax checker modified the TAF otherwise false.
*/
private boolean pythonModifiedTAF = false;
private FindReplaceDlg findDlg; private FindReplaceDlg findDlg;
/** /**
@ -1099,6 +1095,7 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
Menu fileMenu = new Menu(menuBar); Menu fileMenu = new Menu(menuBar);
fileMenuItem.setMenu(fileMenu); fileMenuItem.setMenu(fileMenu);
fileMenu.addListener(SWT.Show, new Listener() { fileMenu.addListener(SWT.Show, new Listener() {
@Override
public void handleEvent(Event event) { public void handleEvent(Event event) {
setAltFlagForEditorTafTabComp(); setAltFlagForEditorTafTabComp();
} }
@ -1210,6 +1207,7 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
Menu optionsMenu = new Menu(menuBar); Menu optionsMenu = new Menu(menuBar);
optionsMenuItem.setMenu(optionsMenu); optionsMenuItem.setMenu(optionsMenu);
optionsMenu.addListener(SWT.Show, new Listener() { optionsMenu.addListener(SWT.Show, new Listener() {
@Override
public void handleEvent(Event event) { public void handleEvent(Event event) {
setAltFlagForEditorTafTabComp(); setAltFlagForEditorTafTabComp();
} }
@ -1245,31 +1243,16 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
autoPrintMI.setText("A&uto Print"); autoPrintMI.setText("A&uto Print");
autoPrintMI.setSelection(configMgr autoPrintMI.setSelection(configMgr
.getResourceAsBoolean(ResourceTag.AutoPrint)); .getResourceAsBoolean(ResourceTag.AutoPrint));
autoPrintMI.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
}
});
// Update Times on Format menu item // Update Times on Format menu item
updateTimesFormatMI = new MenuItem(optionsMenu, SWT.CHECK); updateTimesFormatMI = new MenuItem(optionsMenu, SWT.CHECK);
updateTimesFormatMI.setText("U&pdate Times on Format"); updateTimesFormatMI.setText("U&pdate Times on Format");
updateTimesFormatMI.setSelection(configMgr updateTimesFormatMI.setSelection(configMgr
.getResourceAsBoolean(ResourceTag.UpdateTimes)); .getResourceAsBoolean(ResourceTag.UpdateTimes));
updateTimesFormatMI.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
}
});
// Send Collective menu item // Send Collective menu item
sendCollectMI = new MenuItem(optionsMenu, SWT.CHECK); sendCollectMI = new MenuItem(optionsMenu, SWT.CHECK);
sendCollectMI.setText("&Send in Collective"); sendCollectMI.setText("&Send in Collective");
sendCollectMI.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
}
});
} }
/** /**
@ -1289,6 +1272,7 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
Menu editMenu = new Menu(menuBar); Menu editMenu = new Menu(menuBar);
editMenuItem.setMenu(editMenu); editMenuItem.setMenu(editMenu);
editMenu.addListener(SWT.Show, new Listener() { editMenu.addListener(SWT.Show, new Listener() {
@Override
public void handleEvent(Event event) { public void handleEvent(Event event) {
setAltFlagForEditorTafTabComp(); setAltFlagForEditorTafTabComp();
} }
@ -1397,6 +1381,7 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
Menu helpMenu = new Menu(menuBar); Menu helpMenu = new Menu(menuBar);
helpMenuItem.setMenu(helpMenu); helpMenuItem.setMenu(helpMenu);
helpMenu.addListener(SWT.Show, new Listener() { helpMenu.addListener(SWT.Show, new Listener() {
@Override
public void handleEvent(Event event) { public void handleEvent(Event event) {
setAltFlagForEditorTafTabComp(); setAltFlagForEditorTafTabComp();
} }
@ -2093,12 +2078,6 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
wrapChk = new Button(controlsComp, SWT.CHECK); wrapChk = new Button(controlsComp, SWT.CHECK);
wrapChk.setText("Wrap"); wrapChk.setText("Wrap");
configMgr.setDefaultFontAndColors(wrapChk); configMgr.setDefaultFontAndColors(wrapChk);
wrapChk.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent event) {
}
});
String wrapStr = configMgr.getDataAsString(ResourceTag.Wrap); String wrapStr = configMgr.getDataAsString(ResourceTag.Wrap);
if (wrapStr.compareTo("word") == 0) { if (wrapStr.compareTo("word") == 0) {
@ -2909,20 +2888,10 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
* @return errorInTaf true when syntax error found otherwise false * @return errorInTaf true when syntax error found otherwise false
*/ */
private boolean checkSyntaxInEditor(boolean doLogMessage) { private boolean checkSyntaxInEditor(boolean doLogMessage) {
// Get the content of the Taf Editor.
// Assume editorTafTabComp is for the active tab.
// DR15477: trim blank lines before Syntax Checking
String in = (editorTafTabComp.getTextEditorControl().getText().trim());
// Declare variables for processing the editor's contents.
boolean errorInTaf = false;
int idx1 = 0;
int currentLineNo = 0;
clearSyntaxErrorLevel(); clearSyntaxErrorLevel();
st = editorTafTabComp.getTextEditorControl(); st = editorTafTabComp.getTextEditorControl();
final Map<StyleRange, String> syntaxMap = new HashMap<StyleRange, String>(); final Map<StyleRange, String> syntaxMap = new HashMap<StyleRange, String>();
ArrayList<String> tafList = new ArrayList<String>();
st.addMouseTrackListener(new MouseTrackAdapter() { st.addMouseTrackListener(new MouseTrackAdapter() {
@Override @Override
public void mouseHover(MouseEvent e) { public void mouseHover(MouseEvent e) {
@ -2952,12 +2921,59 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
} }
}); });
ArrayList<String> tList = new ArrayList<String>(); // Get the content of the Taf Editor.
// Assume editorTafTabComp is for the active tab.
// DR15477: trim blank lines before Syntax Checking
String in = (editorTafTabComp.getTextEditorControl().getText().trim());
checkSyntax(in, syntaxMap, doLogMessage);
// reset everything since checkSyntax may have altered the TAF
st.setStyleRange(null);
syntaxMap.clear();
/*
* TODO Refactor all of this to be smarter. Right now it's kind of dumb
* in that the python syntax check can potentially alter the datetime of
* the TAF and/or the whitespace/spacing of the TAF. If that occurs, the
* python does NOT return the map of syntax problems detected, so you
* have to run the syntax check again against the properly formatted
* TAF.
*
* Due to the way the code is currently structured, there's not an easy
* way to cleanly do the second syntax check only if necessary while
* keeping the style ranges correctly lined up. Therefore, for now we
* will run the syntax check once against the TAF(s) (ie the code
* above), and just presume that it altered the TAF's datetime or
* whitespace. Then we will run it a second time (ie the code below)
* since it should be guaranteed at that point to return a syntax map if
* there were any syntax issues detected.
*/
in = editorTafTabComp.getTextEditorControl().getText().trim();
boolean errorInTaf = checkSyntax(in, syntaxMap, doLogMessage);
st.setStyleRange(null);
Set<StyleRange> srs = syntaxMap.keySet();
for (StyleRange sr : srs) {
st.setStyleRange(sr);
}
return errorInTaf;
}
private boolean checkSyntax(String in, Map<StyleRange, String> syntaxMap,
boolean doLogMessage) {
boolean errorInTaf = false;
List<String> checkedTafs = new ArrayList<String>();
List<String> tList = new ArrayList<String>();
Map<StyleRange, String> sMap = new HashMap<StyleRange, String>(); Map<StyleRange, String> sMap = new HashMap<StyleRange, String>();
/*
* Separate each TAF individually and syntax check it, and then
* reassemble the set of TAFs each iteration to ensure the line numbers
* and style range indices will line up correctly.
*/
int idx1 = 0;
while (idx1 > -1) { while (idx1 > -1) {
int idx2 = in.indexOf("TAF", idx1 + 1); int idx2 = in.indexOf("TAF", idx1 + 1);
boolean errInTaf = false;
String taf; String taf;
sMap.clear(); sMap.clear();
tList.clear(); tList.clear();
@ -2966,52 +2982,35 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
} else { } else {
taf = in.substring(idx1); taf = in.substring(idx1);
} }
currentLineNo = st.getLineAtOffset(idx1);
errInTaf = checkSyntaxUsingPython(taf, currentLineNo, sMap, tList,
doLogMessage);
if (pythonModifiedTAF == false) { int currentLineNo = st.getLineAtOffset(idx1);
// TAF not changed prepare to check next taf. errorInTaf |= checkSyntaxUsingPython(taf, currentLineNo, sMap,
tafList.add(tList.get(0)); tList, doLogMessage);
if (errInTaf) { for (StyleRange skey : sMap.keySet()) {
for (StyleRange skey : sMap.keySet()) { syntaxMap.put(skey, sMap.get(skey));
syntaxMap.put(skey, sMap.get(skey));
}
}
errorInTaf |= errInTaf;
idx1 = idx2;
} else {
// Python modified the TAF. Assume self correction.
// Ignore errors and set up to check the corrected taf.
StringBuilder sb = new StringBuilder();
for (String tempTaf : tafList) {
sb.append(tempTaf);
sb.append("\n");
}
sb.append(tList.get(0));
sb.append("\n");
if (idx2 > -1) {
sb.append(in.substring(idx2));
}
in = sb.toString();
st.setText(in);
} }
}
StringBuilder sb = new StringBuilder(); String tafAfterCheck = tList.get(0);
checkedTafs.add(tafAfterCheck);
StringBuilder sb = new StringBuilder();
for (String checkedTaf : checkedTafs) {
sb.append(checkedTaf);
sb.append("\n");
}
int lengthChecked = sb.length();
for (String taf : tafList) { if (idx2 > -1) {
sb.append(taf); sb.append(in.substring(idx2));
sb.append("\n"); }
} in = sb.toString();
st.setText(in);
st.setText(sb.toString()); /*
st.setStyleRange(null); * Set idx1 to the next TAF after all the text that has already been
* checked. This ensures we won't hit the very rare infinite loop
Set<StyleRange> srs = syntaxMap.keySet(); * that occurs if tafAfterCheck comes back with two TAFS inside it.
*/
for (StyleRange sr : srs) { idx1 = in.indexOf("TAF", lengthChecked);
st.setStyleRange(sr);
} }
return errorInTaf; return errorInTaf;
@ -3036,32 +3035,19 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private boolean checkSyntaxUsingPython(String in, int currentLineNo, private boolean checkSyntaxUsingPython(String in, int currentLineNo,
Map<StyleRange, String> syntaxMap, ArrayList<String> tafList, Map<StyleRange, String> syntaxMap, List<String> tafList,
boolean doLogMessage) { boolean doLogMessage) {
// TODO remove
getSitesInTaf(in);
// Declare variables for processing the editor's contents.
boolean errorInTaf = false; boolean errorInTaf = false;
int[] range = new int[] { 0, 0, 0, 0 }; int[] range = new int[] { 0, 0, 0, 0 };
pythonModifiedTAF = false;
// Assume editorTafTabComp is for the active tab. in = in.trim();
st = editorTafTabComp.getTextEditorControl(); Map<String, Object> resultMap = parseText(in, editorTafTabComp.getBBB());
HashMap<String, Object> resultMap = parseText(in,
editorTafTabComp.getBBB());
HashMap<String, Object> parsedText = (HashMap<String, Object>) resultMap
.get("result");
String newText = (String) resultMap.get("text"); String newText = (String) resultMap.get("text");
Map<String, Object> parsedText = (Map<String, Object>) resultMap
.get("result");
String newTime = (String) resultMap.get("headerTime"); String newTime = (String) resultMap.get("headerTime");
tafList.add(newText); tafList.add(newText);
// Python may change the TAF let the caller handle it prior to setting
// up any error information.
if (in.trim().equals(newText.trim()) == false) {
pythonModifiedTAF = true;
return true;
}
editorTafTabComp.setLargeTF(newTime); editorTafTabComp.setLargeTF(newTime);
java.util.List<String> results; java.util.List<String> results;
StringBuilder errorMsg = new StringBuilder(); StringBuilder errorMsg = new StringBuilder();
@ -3327,7 +3313,7 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
* @return -- the decoded TAF * @return -- the decoded TAF
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private HashMap<String, Object> parseText(String text, String bbb) { private Map<String, Object> parseText(String text, String bbb) {
IPathManager pm = PathManagerFactory.getPathManager(); IPathManager pm = PathManagerFactory.getPathManager();
@ -3339,10 +3325,8 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
File baseDir = pm.getFile(baseContext, "aviation" File baseDir = pm.getFile(baseContext, "aviation"
+ IPathManager.SEPARATOR + "python"); + IPathManager.SEPARATOR + "python");
HashMap<String, Object> resultMap = null; Map<String, Object> resultMap = null;
Map<String, Object> argMap = new HashMap<String, Object>();
HashMap<String, Object> map = new HashMap<String, Object>();
try { try {
if (parsePythonScript == null) { if (parsePythonScript == null) {
parsePythonScript = new PythonScript(baseFile.getPath(), parsePythonScript = new PythonScript(baseFile.getPath(),
@ -3351,13 +3335,13 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
TafViewerEditorDlg.class.getClassLoader()); TafViewerEditorDlg.class.getClassLoader());
} }
parsePythonScript.instantiatePythonClass("parser", "Decoder", null); parsePythonScript.instantiatePythonClass("parser", "Decoder", null);
map.put("text", text); argMap.put("text", text);
map.put("bbb", bbb); argMap.put("bbb", bbb);
Object com = parsePythonScript.execute("parseFromJava", "parser", Object com = parsePythonScript.execute("parseFromJava", "parser",
map); argMap);
resultMap = (HashMap<String, Object>) com; resultMap = (Map<String, Object>) com;
} catch (JepException e) { } catch (JepException e) {
e.printStackTrace(); statusHandler.error("Error parsing TAF", e);
} }
return resultMap; return resultMap;
} }
@ -4423,6 +4407,7 @@ public class TafViewerEditorDlg extends CaveSWTDialog implements ITafSettable,
* *
* @see com.raytheon.viz.aviation.editor.ITafSettable#getViewerTabList() * @see com.raytheon.viz.aviation.editor.ITafSettable#getViewerTabList()
*/ */
@Override
public List<ViewerTab> getViewerTabList() { public List<ViewerTab> getViewerTabList() {
return modelsTabs; return modelsTabs;
} }