blob: 62df794581ea3471516ab2997e66a5bfd4a5e148 [file] [log] [blame]
package org.eclipse.dltk.tcl.internal.debug;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.debug.core.DebugException;
import org.eclipse.dltk.compiler.CharOperation;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IMethod;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ISourceRange;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.dbgp.commands.IDbgpExtendedCommands;
import org.eclipse.dltk.dbgp.exceptions.DbgpException;
import org.eclipse.dltk.debug.core.IHotCodeReplaceProvider;
import org.eclipse.dltk.debug.core.model.IScriptDebugTarget;
import org.eclipse.dltk.debug.core.model.IScriptThread;
public class TclHotCodeReplaceProvider implements IHotCodeReplaceProvider {
public TclHotCodeReplaceProvider() {
}
@Override
public void performCodeReplace(IScriptDebugTarget target,
IResource[] resources) throws DebugException {
final IScriptThread[] threads = (IScriptThread[]) target.getThreads();
if (threads.length > 0) {
final IDbgpExtendedCommands extCmds = threads[0].getDbgpSession()
.getExtendedCommands();
for (int i = 0; i < resources.length; ++i) {
final String code = getResourceReplacementCode(resources[i]);
if (code != null) {
try {
extCmds.evaluate(code);
} catch (DbgpException e) {
TclDebugPlugin.log(e);
}
}
}
}
}
private String getResourceReplacementCode(IResource resource)
throws DebugException {
final ISourceModule module = (ISourceModule) DLTKCore
.create((IFile) resource);
if (module == null) {
return null;
}
final List<IMethod> procList = new ArrayList<>();
try {
module.accept(element -> {
if (element.getElementType() == IModelElement.METHOD) {
procList.add((IMethod) element);
return false;
}
return true;
});
if (procList.isEmpty()) {
return null;
}
final char[] input = org.eclipse.dltk.internal.core.util.Util
.getResourceContentsAsCharArray((IFile) resource);
final StringBuffer sb = new StringBuffer();
for (final IMethod method : procList) {
final String[] types = collectNamespaces(method);
if (types != null) {
for (int j = 0; j < types.length; ++j) {
sb.append("namespace eval " + types[j] + " {\n"); //$NON-NLS-1$ //$NON-NLS-2$
}
sb.append("proc "); //$NON-NLS-1$
sb.append(method.getElementName());
final ISourceRange nameRange = method.getNameRange();
final int nameEnd = nameRange.getLength()
+ nameRange.getOffset();
final ISourceRange sourceRange = method.getSourceRange();
sb.append(input, nameEnd, sourceRange.getOffset()
+ sourceRange.getLength() - nameEnd);
sb.append("\n"); //$NON-NLS-1$
for (int j = 0; j < types.length; ++j) {
sb.append("}\n"); //$NON-NLS-1$
}
}
}
if (sb.length() == 0) {
return null;
}
return sb.toString();
} catch (ModelException e) {
TclDebugPlugin.log(e);
return null;
}
}
/**
* @param method
* @return
*/
private String[] collectNamespaces(IMethod method) {
final List<String> types = new ArrayList<>();
IModelElement parent = method.getParent();
while (parent.getElementType() == IModelElement.TYPE) {
types.add(parent.getElementName());
parent = parent.getParent();
}
if (parent.getElementType() != IModelElement.SOURCE_MODULE) {
return null;
}
if (types.isEmpty()) {
return CharOperation.NO_STRINGS;
}
Collections.reverse(types);
return types.toArray(new String[types.size()]);
}
}