package org.eclipse.dltk.tcl.internal.core.serialization;
import java.io.IOException;
import java.io.OutputStream;
import org.eclipse.dltk.compiler.problem.DefaultProblemIdentifier;
import org.eclipse.dltk.compiler.problem.IProblem;
import org.eclipse.dltk.compiler.problem.ProblemCollector;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.caching.AbstractDataSaver;
import org.eclipse.dltk.tcl.ast.ComplexString;
import org.eclipse.dltk.tcl.ast.Script;
import org.eclipse.dltk.tcl.ast.StringArgument;
import org.eclipse.dltk.tcl.ast.Substitution;
import org.eclipse.dltk.tcl.ast.TclArgument;
import org.eclipse.dltk.tcl.ast.TclArgumentList;
import org.eclipse.dltk.tcl.ast.TclCodeModel;
import org.eclipse.dltk.tcl.ast.TclCommand;
import org.eclipse.dltk.tcl.ast.TclModule;
import org.eclipse.dltk.tcl.ast.VariableReference;
import org.eclipse.dltk.tcl.definitions.Command;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
public class TclASTSaver extends AbstractDataSaver implements ITclASTConstants {
private int moduleSize;
public void writeInt(int value) throws IOException {
if (moduleSize < Byte.MAX_VALUE) {
out.writeByte(value);
} else if (moduleSize < Short.MAX_VALUE) {
out.writeShort(value);
} else {
out.writeInt(value);
}
}
/**
* @since 2.0
*/
public void save(TclModule module, ProblemCollector dltkProblems,
OutputStream stream) throws IOException {
saveModule(module);
saveProblems(dltkProblems);
saveTo(stream);
stream.close();
}
private void saveModule(TclModule module) throws IOException {
out.writeByte(TAG_MODULE);
out.writeInt(moduleSize = module.getSize());
EList<TclCommand> statements = module.getStatements();
out.writeInt(statements.size());
for (TclCommand tclCommand : statements) {
out(tclCommand);
}
TclCodeModel codeModel = module.getCodeModel();
if (codeModel != null) {
out.writeBoolean(true);
EList<String> delimeters = codeModel.getDelimeters();
out.writeInt(delimeters.size());
for (String del : delimeters) {
writeString(del);
}
EList<Integer> lineOffsets = codeModel.getLineOffsets();
out.writeInt(lineOffsets.size());
for (Integer integer : lineOffsets) {
writeInt(integer.intValue());
}
} else {
out.writeBoolean(false);
}
}
private void saveProblems(ProblemCollector collector) throws IOException {
if (collector != null) {
int size = collector.getErrors().size();
out.writeInt(size);
collector.copyTo(problem -> {
try {
saveProblem(problem);
} catch (IOException e) {
if (DLTKCore.DEBUG) {
e.printStackTrace();
}
}
});
} else {
out.writeInt(0);
}
}
private void saveProblem(IProblem problem) throws IOException {
out.writeByte(TAG_PROBLEM_ID_AS_STRING);
writeString(DefaultProblemIdentifier.encode(problem.getID()));
writeString(problem.getMessage());
writeInt(problem.getSourceStart());
writeInt(problem.getSourceEnd() - problem.getSourceStart());
if (problem.getArguments() != null) {
out.writeInt(problem.getArguments().length);
for (String arg : problem.getArguments()) {
writeString(arg);
}
} else {
out.writeInt(0);
}
out.writeBoolean(problem.isError());
out.writeBoolean(problem.isWarning());
writeInt(problem.getSourceLineNumber());
}
public void out(TclArgument arg) throws IOException {
if (arg instanceof StringArgument) {
// Simple absolute or relative source'ing.
StringArgument argument = (StringArgument) arg;
String value = argument.getValue();
out.writeByte(TAG_STRING_ARGUMENT);
writeInt(arg.getStart());
writeInt(arg.getEnd() - arg.getStart());
writeString(value);
} else if (arg instanceof ComplexString) {
ComplexString carg = (ComplexString) arg;
// String cargValue = carg.getValue();
out.writeByte(TAG_COMPLEX_STRING_ARGUMENT);
out.writeInt(carg.getKind());
writeInt(arg.getStart());
writeInt(arg.getEnd() - arg.getStart());
// writeString(cargValue);
EList<TclArgument> eList = carg.getArguments();
out.writeInt(eList.size());
for (TclArgument tclArgument : eList) {
out(tclArgument);
}
} else if (arg instanceof Script) {
Script st = (Script) arg;
EList<TclCommand> eList = st.getCommands();
out.writeByte(TAG_SCRIPT_ARGUMENT);
writeInt(arg.getStart());
writeInt(arg.getEnd() - arg.getStart());
writeInt(st.getContentStart());
writeInt(st.getContentEnd() - st.getContentStart());
out.writeInt(eList.size());
for (TclCommand tclArgument : eList) {
out(tclArgument);
}
} else if (arg instanceof VariableReference) {
VariableReference var = (VariableReference) arg;
out.writeByte(TAG_VARIABLE_ARGUMENT);
writeInt(arg.getStart());
writeInt(arg.getEnd() - arg.getStart());
writeString(var.getName());
TclArgument index = var.getIndex();
if (index == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out(index);
}
} else if (arg instanceof Substitution) {
Substitution st = (Substitution) arg;
EList<TclCommand> eList = st.getCommands();
out.writeByte(TAG_SUBSTITUTION_ARGUMENT);
writeInt(arg.getStart());
writeInt(arg.getEnd() - arg.getStart());
out.writeInt(eList.size());
for (TclCommand tclArgument : eList) {
out(tclArgument);
}
} else if (arg instanceof TclArgumentList) {
TclArgumentList st = (TclArgumentList) arg;
out.writeByte(TAG_ARGUMENT_LIST_ARGUMENT);
out.writeInt(st.getKind());
writeInt(arg.getStart());
writeInt(arg.getEnd() - arg.getStart());
EList<TclArgument> arguments = st.getArguments();
out.writeInt(arguments.size());
for (TclArgument tclArgument : arguments) {
out(tclArgument);
}
storeERef(st.getDefinitionArgument());
}
}
public void out(TclCommand command) throws IOException {
out.writeByte(TAG_COMMAND);
writeInt(command.getStart());
writeInt(command.getEnd());
writeString(command.getQualifiedName());
Command def = command.getDefinition();
storeERef(def);
out(command.getName());
out.writeInt(command.getArguments().size());
EList<TclArgument> eList = command.getArguments();
for (TclArgument tclArgument : eList) {
out(tclArgument);
}
}
private void storeERef(EObject def) throws IOException {
if (def == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
URI uri = EcoreUtil.getURI(def);
String defURI = uri.fragment();
writeString(defURI);
}
}
}