package org.eclipse.dltk.tcl.indexing;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.dltk.core.builder.IBuildContext;
import org.eclipse.dltk.core.builder.ISourceLineTracker;
import org.eclipse.dltk.tcl.ast.StringArgument;
import org.eclipse.dltk.tcl.ast.TclArgument;
import org.eclipse.dltk.tcl.ast.TclCommand;
import org.eclipse.dltk.tcl.parser.TclVisitor;
public class SpawnpointCollector extends TclVisitor {
public static class SpawnpointInfo {
public Set<String> commands;
public int charStart;
public int charEnd;
}
private static final String PROC_COMMAND = "proc"; //$NON-NLS-1$
private final IBuildContext buildContext;
private final Set<String> spawnCommands;
public SpawnpointCollector(IBuildContext buildContext,
Set<String> spawnCommands) {
this.buildContext = buildContext;
this.spawnCommands = spawnCommands;
}
private ISourceLineTracker lineTracker;
public void setLineTracker(ISourceLineTracker lineTracker) {
this.lineTracker = lineTracker;
}
private StringArgument getStringArgument(TclCommand command, int index) {
if (index < command.getArguments().size()) {
TclArgument argument = command.getArguments().get(index);
if (argument instanceof StringArgument) {
return (StringArgument) argument;
}
}
return null;
}
@Override
public boolean visit(TclCommand command) {
if (PROC_COMMAND.equals(command.getQualifiedName())
&& command.getArguments().size() == 3) {
final StringArgument procName = getStringArgument(command, 0);
if (procName != null && spawnCommands.contains(procName.getValue())) {
return false;
}
} else if (spawnCommands.contains(command.getQualifiedName())) {
if (lineTracker == null) {
lineTracker = buildContext.getLineTracker();
}
int lineNumber = lineTracker.getLineNumberOfOffset(command
.getStart());
addSpawnpoint(lineNumber, command.getQualifiedName(), command
.getStart(), command.getEnd());
}
return true;
}
public final Map<Integer, SpawnpointInfo> spawnpoints = new HashMap<Integer, SpawnpointInfo>();
private void addSpawnpoint(int lineNumber, String commandName, int start,
int end) {
Integer lineObj = Integer.valueOf(lineNumber);
SpawnpointInfo info = spawnpoints.get(lineObj);
if (info == null) {
info = new SpawnpointInfo();
info.commands = Collections.singleton(commandName);
info.charStart = start;
info.charEnd = end;
spawnpoints.put(lineObj, info);
} else {
if (!info.commands.contains(commandName)) {
final Set<String> commandNames = new HashSet<String>();
commandNames.addAll(info.commands);
commandNames.add(commandName);
info.commands = commandNames;
}
if (start < info.charStart) {
info.charStart = start;
}
if (end > info.charEnd) {
info.charEnd = end;
}
}
}
}