package org.eclipse.dltk.tcl.internal.core.serialization;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.dltk.compiler.problem.DefaultProblem;
import org.eclipse.dltk.compiler.problem.DefaultProblemIdentifier;
import org.eclipse.dltk.compiler.problem.IProblemIdentifier;
import org.eclipse.dltk.compiler.problem.IProblemReporter;
import org.eclipse.dltk.compiler.problem.ProblemSeverities;
import org.eclipse.dltk.compiler.problem.ProblemSeverity;
import org.eclipse.dltk.core.RuntimePerformanceMonitor;
import org.eclipse.dltk.core.RuntimePerformanceMonitor.PerformanceNode;
import org.eclipse.dltk.core.caching.AbstractDataLoader;
import org.eclipse.dltk.tcl.ast.AstFactory;
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.dltk.tcl.definitions.ComplexArgument;
import org.eclipse.dltk.tcl.definitions.Scope;
import org.eclipse.dltk.tcl.parser.definitions.DefinitionManager;
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.resource.Resource;
public class TclASTLoader extends AbstractDataLoader implements
ITclASTConstants {
private Scope[] scopes;
int moduleSize = 0;
public TclASTLoader(InputStream stream) throws IOException {
super(stream);
scopes = DefinitionManager.getInstance().getScopes();
}
public int readInt() throws IOException {
if (moduleSize < Byte.MAX_VALUE) {
return in.readByte();
} else if (moduleSize < Short.MAX_VALUE) {
return in.readShort();
} else {
return in.readInt();
}
}
public TclModule getModule(IProblemReporter collector) throws Exception {
PerformanceNode p = RuntimePerformanceMonitor.begin();
// Load strings
readStrings();
int moduleTag = in.readByte(); // TAG_MODULE
switch (moduleTag) {
case TAG_MODULE:
TclModule module = AstFactory.eINSTANCE.createTclModule();
moduleSize = in.readInt();
module.setSize(moduleSize);// module.getSize()
EList<TclCommand> statements = module.getStatements();
int statemetsSize = in.readInt(); // statements.size()
for (int i = 0; i < statemetsSize; ++i) {
statements.add(readCommand());
}
boolean hasCodeModel = in.readBoolean();
if (hasCodeModel) {
TclCodeModel codeModel = AstFactory.eINSTANCE
.createTclCodeModel();
module.setCodeModel(codeModel);
int delimSize = in.readInt();
EList<String> delimList = codeModel.getDelimeters();
for (int i = 0; i < delimSize; i++) {
delimList.add(readString());
}
int offsets = in.readInt();
EList<Integer> offList = codeModel.getLineOffsets();
for (int i = 0; i < offsets; i++) {
offList.add(Integer.valueOf(readInt()));
}
}
// Restore problems
int problemsSize = in.readInt();
for (int i = 0; i < problemsSize; i++) {
loadProblem(collector);
}
p.done("Tcl", "Load persisted AST", 0);
in.close();
return module;
}
p.done("Tcl", "Load persisted AST", 0);
in.close();
return null;
}
private void loadProblem(IProblemReporter collector) throws IOException {
int tag = in.readByte();// TAG_PROBLEM);
if (tag != TAG_PROBLEM && tag != TAG_PROBLEM_ID_AS_STRING) {
return;
}
IProblemIdentifier id;
if (tag == TAG_PROBLEM) {
id = DefaultProblemIdentifier.decode(in.readInt());
} else {
id = DefaultProblemIdentifier.decode(readString());
}
String message = readString();
int start = readInt();
int end = readInt() + start;
int argsSize = in.readInt();
String[] args = null;
if (argsSize > 0) {
args = new String[argsSize];
}
for (int i = 0; i < argsSize; i++) {
args[i] = readString();
}
boolean error = in.readBoolean();
boolean warning = in.readBoolean();
int lineNumber = readInt();
ProblemSeverity sev = ProblemSeverity.INFO;
if (error) {
sev = ProblemSeverities.Error;
} else if (warning) {
sev = ProblemSeverities.Warning;
}
collector.reportProblem(new DefaultProblem(message, id, args, sev,
start, end, lineNumber));
}
public TclArgument readArgument() throws IOException {
int argType = in.readByte();
switch (argType) {
case TAG_STRING_ARGUMENT: {
// Simple absolute or relative source'ing.
StringArgument argument = AstFactory.eINSTANCE
.createStringArgument();
argument.setStart(readInt());
argument.setEnd(readInt() + argument.getStart());
final String value = readString();
argument.setValue(value);
argument.setRawValue(value);
return argument;
}
case TAG_COMPLEX_STRING_ARGUMENT: {
ComplexString carg = AstFactory.eINSTANCE.createComplexString();
carg.setKind(in.readInt());
carg.setStart(readInt());
carg.setEnd(readInt() + carg.getStart());
// carg.setValue(readString());
EList<TclArgument> eList = carg.getArguments();
int size = in.readInt();
for (int i = 0; i < size; ++i) {
eList.add(readArgument());
}
return carg;
}
case TAG_SCRIPT_ARGUMENT: {
Script st = AstFactory.eINSTANCE.createScript();
EList<TclCommand> eList = st.getCommands();
st.setStart(readInt());
st.setEnd(readInt() + st.getStart());
st.setContentStart(readInt());
st.setContentEnd(readInt() + st.getContentStart());
int size = in.readInt();
for (int i = 0; i < size; ++i) {
eList.add(readCommand());
}
return st;
}
case TAG_VARIABLE_ARGUMENT: {
VariableReference var = AstFactory.eINSTANCE
.createVariableReference();
var.setStart(readInt());
var.setEnd(readInt() + var.getStart());
var.setName(readString());
boolean index = in.readBoolean();
if (index) {
var.setIndex(readArgument());
}
return var;
}
case TAG_SUBSTITUTION_ARGUMENT: {
Substitution st = AstFactory.eINSTANCE.createSubstitution();
EList<TclCommand> eList = st.getCommands();
st.setStart(readInt());
st.setEnd(readInt() + st.getStart());
int size = in.readInt();
for (int i = 0; i < size; ++i) {
eList.add(readCommand());
}
return st;
}
case TAG_ARGUMENT_LIST_ARGUMENT: {
TclArgumentList st = AstFactory.eINSTANCE.createTclArgumentList();
st.setKind(in.readInt());
st.setStart(readInt());
st.setEnd(readInt() + st.getStart());
EList<TclArgument> arguments = st.getArguments();
int size = in.readInt();
for (int i = 0; i < size; ++i) {
arguments.add(readArgument());
}
// boolean originalArg = in.readBoolean();
// if (originalArg) {
// st.setOriginalArgument(readArgument());
// }
EObject def = restoreERef();
if (def instanceof ComplexArgument) {
st.setDefinitionArgument((ComplexArgument) def);
}
return st;
}
}
throw new IOException("Failed to load command argument.");
}
public TclCommand readCommand() throws IOException {
int tagCommand = in.readByte();
if (tagCommand != TAG_COMMAND) {
throw new IOException("Incorrect command tag");
}
TclCommand command = AstFactory.eINSTANCE.createTclCommand();
command.setStart(readInt());
command.setEnd(readInt() + command.getStart());
command.setQualifiedName(readString());
EObject def = restoreERef();
if (def instanceof Command) {
command.setDefinition((Command) def);
}
command.setName(readArgument());
int size = in.readInt();// command.getArguments().size());
EList<TclArgument> eList = command.getArguments();
for (int i = 0; i < size; ++i) {
eList.add(readArgument());
}
return command;
}
private EObject restoreERef() throws IOException {
PerformanceNode p = RuntimePerformanceMonitor.begin();
EObject def = null;
boolean has = in.readBoolean();
if (!has) {
return null;
}
String definitionURI = readString();
if (definitionURI != null) {
for (Scope scope : scopes) {
Resource eResource = scope.eResource();
URI frag = eResource.getURI().appendFragment(definitionURI);
EObject eObject = DefinitionManager.getInstance()
.getEobjectCache().get(frag);
if (eObject != null) {
return eObject;
}
}
}
p.done("Tcl", "Restore eREF", 0);
return def;
}
}