/* * #%~ * org.overture.ide.core * %% * Copyright (C) 2008 - 2014 Overture * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #~% */ package org.overture.ide.core.parser; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.overture.ast.lex.LexLocation; import org.overture.ast.node.INode; import org.overture.ide.core.ICoreConstants; import org.overture.ide.core.VdmCore; import org.overture.ide.core.resources.IVdmProject; import org.overture.ide.core.resources.IVdmSourceUnit; import org.overture.ide.core.utility.FileUtility; import org.overture.parser.lex.BacktrackInputReader.ReaderType; import org.overture.parser.messages.VDMError; import org.overture.parser.messages.VDMWarning; public abstract class AbstractParserParticipant implements ISourceParser { protected String natureId; protected IVdmProject project; public void setNatureId(String natureId) { this.natureId = natureId; } public void setProject(IVdmProject project) { this.project = project; } /** * Parses a file and updates file markers and the AstManager with the result */ public void parse(IVdmSourceUnit file) { ParseResult result; try { LexLocation.getAllLocations().clear(); result = startParse(file, FileUtility.makeString(FileUtility.getContent(file.getFile())), file.getFile().getCharset()); setFileMarkers(file.getFile(), result); if (result != null && result.getAst() != null) { file.reconcile(result.getAst(), result.hasParseErrors()); } } catch (CoreException e) { if (VdmCore.DEBUG) { VdmCore.log("AbstractParserParticipant:parse IVdmSourceUnit", e); } } } /** * Parses a file and updates file markers and the AstManager with the result */ public void parse(IVdmSourceUnit file, String data, boolean forceAstUpdate) { ParseResult result; try { if (file.getFile().isLinked() && !file.getFile().getLocation().toFile().exists()) { FileUtility.deleteMarker(file.getFile(), IMarker.PROBLEM, ICoreConstants.PLUGIN_ID); addError(file.getFile(), "Linked file not found " + file.getFile(), 0); if (forceAstUpdate) { file.reconcile(null, true); } } else { LexLocation.getAllLocations().clear(); result = startParse(file, data, file.getFile().getCharset()); setFileMarkers(file.getFile(), result); if (result != null && result.getAst() != null) { if (forceAstUpdate) { file.reconcile(result.getAst(), result.hasParseErrors()); } } } } catch (CoreException e) { if (e.getStatus().getException() instanceof IOException) { FileUtility.deleteMarker(file.getFile(), IMarker.PROBLEM, ICoreConstants.PLUGIN_ID); if (e.getStatus() != null && e.getStatus().getException() != null) { addError(file.getFile(), e.getStatus().getException().getMessage(), 0); } } else if (VdmCore.DEBUG) { VdmCore.log("AbstractParserParticipant:parse IVdmSourceUnit", e); } if (forceAstUpdate) { file.reconcile(null, true); } } catch (Exception e) { if (VdmCore.DEBUG) { VdmCore.log("AbstractParserParticipant:parse IVdmSourceUnit", e); } FileUtility.deleteMarker(file.getFile(), IMarker.PROBLEM, ICoreConstants.PLUGIN_ID); addError(file.getFile(), "Internal error: " + e.getMessage(), 0); if (forceAstUpdate) { file.reconcile(null, true); } } } /** * Adds markers to a file based on the result. if errors occurred the problem markers are first cleared. * * @param file * the file where the markers should be set * @param result * the result indicating if parse errors occurred * @param content * @throws CoreException */ private void setFileMarkers(IFile file, ParseResult result) throws CoreException { if (file != null) { FileUtility.deleteMarker(file, IMarker.PROBLEM, ICoreConstants.PLUGIN_ID); if (result.hasParseErrors()) { file.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); int previousErrorNumber = -1; for (VDMError error : result.getErrors()) { if (previousErrorNumber == error.number) {// this check is // done to avoid // error fall // through continue; } else { previousErrorNumber = error.number; } FileUtility.addMarker(file, error.toProblemString(), error.location, IMarker.SEVERITY_ERROR, ICoreConstants.PLUGIN_ID, -1); } } IVdmProject vdmProject = (IVdmProject) project.getAdapter(IVdmProject.class); if (result.getWarnings().size() > 0 && vdmProject != null && vdmProject.hasSuppressWarnings()) { for (VDMWarning warning : result.getWarnings()) { FileUtility.addMarker(file, warning.toProblemString(), warning.location, IMarker.SEVERITY_WARNING, ICoreConstants.PLUGIN_ID, -1); } } } } /** * Delegate method for parsing, the methods addWarning and addError should be used to report * * @param file * the file to be parsed * @param content * the content of the file * @param charset * the charset of the content * @return the result of the parse including error report and the AST */ protected abstract ParseResult startParse(IVdmSourceUnit file, String content, String charset); protected void addWarning(IFile file, String message, int lineNumber) { FileUtility.addMarker(file, message, lineNumber, IMarker.SEVERITY_WARNING, ICoreConstants.PLUGIN_ID); } protected void addError(IFile file, String message, int lineNumber) { FileUtility.addMarker(file, message, lineNumber, IMarker.SEVERITY_ERROR, ICoreConstants.PLUGIN_ID); } protected void processInternalError(Throwable e) { System.out.println(e.toString()); }; public static ReaderType findStreamReaderType(IFile file) throws CoreException { ReaderType streamReaderType = ReaderType.Latex; if (file.getFileExtension().endsWith("doc")) { streamReaderType = ReaderType.Doc; } else if (file.getFileExtension().endsWith("docx")) { streamReaderType = ReaderType.Docx; } else if (file.getFileExtension().endsWith("odt")) { streamReaderType = ReaderType.Odf; } return streamReaderType; } public static class ParseResult { private List<INode> ast = null; private List<VDMError> errors = new ArrayList<VDMError>(); private List<VDMWarning> warnings = new ArrayList<VDMWarning>(); private Throwable fatalError; public ParseResult() { } public boolean hasParseErrors() { return errors.size() != 0 || fatalError != null; } public void setAst(List<INode> ast) { // Assert.isNotNull(ast, "AST cannot be null"); // Assert.isTrue(ast.size() != 0, "AST cannot be an empty list"); this.ast = ast; } public List<INode> getAst() { return ast; } public void setWarnings(List<VDMWarning> warnings) { this.warnings.addAll(warnings); } public List<VDMWarning> getWarnings() { return warnings; } public void setErrors(List<VDMError> errors) { this.errors.addAll(errors); } public List<VDMError> getErrors() { return errors; } public void setFatalError(Throwable fatalError) { if (VdmCore.DEBUG) { // fatalError.printStackTrace(); } this.fatalError = fatalError; } public Throwable getFatalError() { return fatalError; } } }