package bluej.stride.framedjava.elements;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import bluej.stride.framedjava.ast.JavaFragment;
import bluej.stride.generic.InteractionManager;
import bluej.utility.Utility;
import nu.xom.Element;
import threadchecker.OnThread;
import threadchecker.Tag;
import bluej.debugger.gentype.Reflective;
import bluej.stride.framedjava.ast.AccessPermission;
import bluej.stride.framedjava.ast.AccessPermissionFragment;
import bluej.stride.framedjava.ast.HighlightedBreakpoint;
import bluej.stride.framedjava.ast.JavaSingleLineDebugHandler;
import bluej.stride.framedjava.ast.JavadocUnit;
import bluej.stride.framedjava.ast.Loader;
import bluej.stride.framedjava.ast.NameDefSlotFragment;
import bluej.stride.framedjava.ast.ParamFragment;
import bluej.stride.framedjava.ast.ThrowsTypeFragment;
import bluej.stride.framedjava.ast.TypeSlotFragment;
import bluej.stride.framedjava.frames.DebugInfo;
import bluej.stride.framedjava.frames.MethodFrameWithBody;
| A parent class which is shared between ConstructorElement and NormalMethodElement.
| These two items have a lot in comment, which is collected here.
|
public abstract class MethodWithBodyElement
extends DocumentContainerCodeElement implements JavaSingleLineDebugHandler{
protected final List<ParamFragment> params;
protected final List<ThrowsTypeFragment> throwsTypes;
protected final List<CodeElement> contents;
protected MethodFrameWithBody<?> frame;
protected AccessPermissionFragment access;
| Constructor when generated from the GUI
|
public MethodWithBodyElement(MethodFrameWithBody<?> frame, AccessPermissionFragment access, List<ParamFragment> params,
List<ThrowsTypeFragment> throwsTypes, List<CodeElement> contents, JavadocUnit documentation, boolean enabled)
{
this.frame = frame;
this.access = access;
this.params = params;
this.throwsTypes = throwsTypes;
this.contents = contents;
this.documentation = documentation;
for (CodeElement c : this.contents) {
c.setParent(this);
}
this.enable = enabled;
if (this.documentation == null) {
this.documentation = new JavadocUnit("");
}
}
| Constructor when loaded from file/clipboard
|
public MethodWithBodyElement(Element el)
{
access = new AccessPermissionFragment(AccessPermission.fromString(el.getAttributeValue("access")));
params = new ArrayList<>();
this.throwsTypes = new ArrayList<>();
contents = new ArrayList<>();
for (int i = 0; i < el.getChildElements().size(); i++) {
final Element child = el.getChildElements().get(i);
switch (child.getLocalName()) {
case "params":
for (int j = 0; j < child.getChildElements().size(); j++) {
params.add(new ParamFragment(child.getChildElements().get(j)));
}
break;
case "throws":
for (int j = 0; j < child.getChildElements().size(); j++) {
throwsTypes.add(new ThrowsTypeFragment(child.getChildElements().get(j)));
}
break;
case "body":
for (int j = 0; j < child.getChildElements().size(); j++) {
CodeElement member = Loader.loadElement(child.getChildElements().get(j));
contents.add(member);
member.setParent(this);
}
break;
case "javadoc":
documentation = new JavadocUnit(child);
break;
}
}
if (documentation == null) {
documentation = new JavadocUnit("");
}
enable = Boolean.valueOf(el.getAttributeValue("enable"));
}
| Constructor when automatically generated, e.g. by Save the World in Greenfoot
|
public MethodWithBodyElement(String access, List<Entry<String,String>> params, List<CodeElement> contents, String documentation)
{
this.access = new AccessPermissionFragment(AccessPermission.fromString(access));
this.contents = new ArrayList<>(contents);
this.documentation = new JavadocUnit(documentation);
this.throwsTypes = new ArrayList<>();
this.params = new ArrayList<>();
if (params != null ) {
for (Entry<String, String> entry : params) {
this.params.add(new ParamFragment(new TypeSlotFragment(entry.getKey(), entry.getKey()), new NameDefSlotFragment(entry.getValue())));
}
}
}
| Helper method for subclasses when generating XML: add access attribute to given XML
|
protected void accessToXML(LocatableElement methodEl)
{
if (access != null) {
methodEl.addAttributeAccess("access", access);
}
}
| Helper method for subclasses when generating XML: add params child element to given XML
|
protected void paramsToXML(Element methodEl)
{
Element paramsEl = new Element("params");
for (ParamFragment param : params) {
paramsEl.appendChild(param.toXML());
}
methodEl.appendChild(paramsEl);
}
| Helper method for subclasses when generating XML: add throws child element to given XML
|
protected void throwsToXML(Element methodEl)
{
Element throwsEl = new Element("throws");
for (ThrowsTypeFragment t : throwsTypes) {
throwsEl.appendChild(t.toXML());
}
methodEl.appendChild(throwsEl);
}
| Helper method for subclasses when generating XML: add body child element to given XML
|
protected void bodyToXML(Element methodEl)
{
Element bodyEl = new Element("body");
for (CodeElement c : contents) {
bodyEl.appendChild(c.toXML());
}
methodEl.appendChild(bodyEl);
}
| Helper method for subclasses when generating Java: Turn throws declaration into Java
|
protected List throwsToJava()
{
if (throwsTypes.isEmpty())
return Collections.emptyList();
ArrayList<JavaFragment> typesAndCommas = throwsTypes.stream().map(ThrowsTypeFragment::getJavaSource).collect(Utility.intersperse(() -> (JavaFragment)f(null, ", ")));
typesAndCommas.add(0, space());
typesAndCommas.add(0, f(frame, "throws"));
typesAndCommas.add(0, space());
return typesAndCommas;
}
| Helper method for subclasses when generating a Frame (in our frame field)
|
@OnThread(Tag.FX)
protected void setupFrame(InteractionManager editor)
{
frame.setAccess(access.getValue());
frame.setDocumentation(documentation.toString());
params.forEach(item -> frame.getParamsPane().addFormal(item.getParamType(), item.getParamName()));
contents.forEach(c -> frame.getCanvas().insertBlockAfter(c.createFrame(editor), null));
throwsTypes.forEach(t -> frame.addThrows(t.getType()));
}
@Override
public List getDeclaredVariablesWithin(CodeElement child)
{
List<LocalParamInfo> vars = new ArrayList<>();
params.forEach(param -> vars.add(new LocalParamInfo(param.getParamType().getContent(), param.getParamName().getContent(), true, this)));
return vars;
}
@Override
public List childrenUpTo(CodeElement c)
{
return contents.subList(0, contents.indexOf(c));
}
@Override
public HighlightedBreakpoint showDebugBefore(DebugInfo debug)
{
return frame.showDebugBefore(debug);
}
@Override
public MethodWithBodyElement getMethodElement()
{
return this;
}
public List getContents()
{
return contents;
}
public abstract String getType();
@Override
public Stream streamContained()
{
return streamContained(contents);
}
@OnThread(Tag.FXPlatform)
public List getQualifiedParamTypes(ClassElement topLevel)
{
return params.stream().map(p -> {
TypeSlotFragment paramType = p.getParamType();
Reflective qualifyType = topLevel.qualifyType(paramType.getContent(), paramType.getPosInSourceDoc());
if (qualifyType == null)
return paramType.getContent();
return qualifyType.getName();
}
).collect(Collectors.toList());
}
public AccessPermission getAccessPermission()
{
return access.getValue();
}
public List getThrowsTypes()
{
return Utility.mapList(throwsTypes, ThrowsTypeFragment::getType);
}
public List getParams()
{
return params;
}
}
top,
use,
map,
abstract class MethodWithBodyElement
. MethodWithBodyElement
. MethodWithBodyElement
. MethodWithBodyElement
. accessToXML
. paramsToXML
. throwsToXML
. bodyToXML
. throwsToJava
. setupFrame
. getDeclaredVariablesWithin
. childrenUpTo
. showDebugBefore
. getMethodElement
. getContents
. getType
. streamContained
. getQualifiedParamTypes
. getAccessPermission
. getThrowsTypes
. getParams
337 neLoCode
+ 11 LoComm