
goal.tools.BreakpointManager Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of runtime Show documentation
Show all versions of runtime Show documentation
A system for running GOAL multi-agent systems.
The newest version!
/**
* The GOAL Runtime Environment. Copyright (C) 2015 Koen Hindriks.
*
* 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 .
*/
package goal.tools;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.collect.ImmutableSet;
import goal.tools.debugger.BreakPoint;
import goal.tools.debugger.BreakPoint.Type;
import goal.tools.errorhandling.Warning;
import krTools.parser.SourceInfo;
import languageTools.analyzer.FileRegistry;
import languageTools.program.Program;
import languageTools.program.actionspec.ActionSpecProgram;
import languageTools.program.actionspec.UserSpecAction;
import languageTools.program.agent.Module;
import languageTools.program.agent.actions.Action;
import languageTools.program.agent.actions.ModuleCallAction;
import languageTools.program.agent.rules.Rule;
import languageTools.program.mas.MASProgram;
import languageTools.program.test.TestProgram;
/**
* Manages breakpoints set by a user in a source file.
*/
public class BreakpointManager {
/**
* Map that keeps track for each file (not necessarily an agent file!) for
* which {@link IParsedObject}s present in that file a breakpoint has been
* set.
*/
private final Set breakpoints;
/**
* A registry of source files and associated parsed programs.
*/
private final FileRegistry registry;
/**
* Creates a breakpoint manager.
*
* @param registry
* A registry of source files that also provides the parsed
* programs for each source file.
*/
public BreakpointManager(FileRegistry registry) {
this.registry = registry;
this.breakpoints = Collections.newSetFromMap(new ConcurrentHashMap());
}
// FIXME: only here to fix DebugTool
public FileRegistry getRegistry() {
return this.registry;
}
public void clear() {
this.breakpoints.clear();
}
/**
* Provides the set of breakpoints that have set for the given file.
*
* @param file
* A source file in which breakpoints can (have) be(en) set.
* @return A set of {@link SourceInfo} objects that indicate where
* breakpoints have been set, or {@code null} if no breakpoints have
* been set for the file.
*/
public Set getBreakpoints() {
return ImmutableSet.copyOf(this.breakpoints);
}
/**
* Sets breakpoints for the given file based on the given set of
* breakpoints. Removes or overwrites all breakpoints that were previously
* set in the file.
*
* Matches the given line numbers with objects on which breakpoints may be
* set but the actual location of the breakpoints that are set may have
* different line numbers.
*
*
* @param file
* The file in which the breakpoints should be set.
* @param bpts
* A set of breakpoints.
*/
public void setBreakpoints(File file, Set bpts) {
// Get the program associated with the file and compute the set of
// possible breakpoint locations.
Program program = this.registry.getProgram(file);
List pbplocs = getBreakpointObjects(program, false);
List pcbplocs = getBreakpointObjects(program, true);
// Find a corresponding breakpoint location that matches with each
// breakpoint.
Set bplocs = new LinkedHashSet<>();
SourceInfo location;
for (BreakPoint bpt : bpts) {
try {
if (bpt.getType() == Type.CONDITIONAL) {
location = addBreakpoint(file, pcbplocs, bpt);
} else {
location = addBreakpoint(file, pbplocs, bpt);
}
} catch (IOException e) {
location = null;
}
if (location == null) {
new Warning("could not add " + bpt + ".").emit();
} else {
bplocs.add(location);
}
}
this.breakpoints.addAll(bplocs);
}
/**
* Match a breakpoint with a possible breakpoint location in the file.
*
* @param pbplocs
* Possible (ordered) set of locations for breakpoints.
* @param bpt
* The breakpoint that should be added.
*
* @return
*
* - -1 if there is a reference, but there is no breakpoint object
* after or on the indicated line
* - A number ≥ lineNumber indicating the line on which a
* breakpoint was set.
*
*/
private static SourceInfo addBreakpoint(File file, List pbplocs, BreakPoint bpt) throws IOException {
for (SourceInfo bp : pbplocs) {
// We may assume that possible breakpoint locations have been
// ordered, so
// the first match is the first object after the given line in the
// given file.
if (definedAfter(file.getCanonicalPath(), bpt.getLine(), bp)) {
return bp;
}
}
return null;
}
/**
* Determines if a source is located after a certain line in a certain file.
*
* @param source
* The referenced file path.
* @param line
* The referenced line number.
* @param bp
* The source to check.
* @return {@code true} iff the given source is located in the given file,
* after or at the start of the given line.
*/
private static boolean definedAfter(String source, int line, SourceInfo bp) {
if (source.equals(bp.getSource())) {
return bp.getLineNumber() >= line;
} else {
return false;
}
}
/**
* Collects the objects in the program on which a breakpoint can be set.
*
* @param program
* A program.
* @param conditionalOnly
* {@code true} means that only code locations relevant for
* setting conditional breakpoints should be returned.
* @return A list of code locations in the program on which a breakpoint can
* be set.
*/
private List getBreakpointObjects(Program program, boolean conditionalOnly) {
List objects = new LinkedList<>();
if (program instanceof MASProgram || program instanceof TestProgram) {
// Breakpoints cannot be set in a MAS or test file.
return objects;
} else if (program instanceof Module) {
// Collect possible breakpoint locations in a module file.
for (Rule rule : ((Module) program).getRules()) {
// Add breakpoint location for rule condition.
if (!conditionalOnly) {
objects.add(rule.getCondition().getSourceInfo());
}
// Add breakpoint location for action of rule.
for (Action> action : rule.getAction()) {
// Add rules of nested rules section but do not add start of
// nested rules section itself.
if (action instanceof ModuleCallAction && ((ModuleCallAction) action).getTarget().isAnonymous()) {
objects.addAll(getBreakpointObjects(((ModuleCallAction) action).getTarget(), conditionalOnly));
} else {
objects.add(action.getSourceInfo());
}
}
}
} else if (program instanceof ActionSpecProgram) {
// Collect possible breakpoint locations in an action specification
// file.
for (UserSpecAction actionSpec : ((ActionSpecProgram) program).getActionSpecifications()) {
// Add pre- and post-conditions.
objects.add(actionSpec.getPrecondition().getSourceInfo());
if (actionSpec.getPositivePostcondition() != null) {
objects.add(actionSpec.getPositivePostcondition().getSourceInfo());
}
if (actionSpec.getNegativePostcondition() != null) {
objects.add(actionSpec.getNegativePostcondition().getSourceInfo());
}
}
}
Collections.sort(objects);
return objects;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy