package bluej.stride.framedjava.ast;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.stream.Stream;
import bluej.stride.framedjava.elements.CodeElement;
import bluej.stride.framedjava.elements.LocatableElement.LocationMap;
import bluej.stride.framedjava.errors.*;
import bluej.stride.framedjava.slots.ExpressionSlot;
import bluej.stride.framedjava.slots.TypeSlot;
import bluej.stride.generic.InteractionManager;
import bluej.utility.javafx.FXPlatformConsumer;
import threadchecker.OnThread;
import threadchecker.Tag;
public class TypeSlotFragment
extends StructuredSlotFragment{
private TypeSlot slot;
private boolean hasEarlyErrors;
public TypeSlotFragment(String content, String javaCode, TypeSlot slot)
{
super(content, javaCode);
this.slot = slot;
}
public TypeSlotFragment(String content, String javaCode)
{
this(content, javaCode, null);
}
@Override
public Map getVars()
{
return Collections.emptyMap();
}
@Override
public String getJavaCode(Destination dest, ExpressionSlot<?> completing, Parser.DummyNameGenerator dummyNameGenerator)
{
if (!dest.substitute() || (content != null && Parser.parseableAsType(content)))
return content;
else{
return dummyNameGenerator.generateNewDummyName();
}
}
@Override
public Stream findEarlyErrors()
{
hasEarlyErrors = true;
if (content != null && content.isEmpty())
return Stream.of(new EmptyError(this, "Type cannot be empty"));
else if (content != null && content.endsWith(";"))
return Stream.of(new UnneededSemiColonError(this, () -> getSlot().setText(content.substring(0, content.length() - 1))));
else if (content == null || !Parser.parseableAsType(content))
return Stream.of(new SyntaxCodeError(this, "Invalid type"));
hasEarlyErrors = false;
return Stream.empty();
}
@Override
@OnThread(Tag.FXPlatform)
public Future> findLateErrors(InteractionManager editor, CodeElement parent,
LocationMap rootPathMap)
{
CompletableFuture<List<DirectSlotError>> f = new CompletableFuture<>();
ArrayList<Integer> indexOfErrors = new ArrayList<>();
ArrayList<String> typesList = new ArrayList<>();
if (hasEarlyErrors)
{
f.complete(Collections.emptyList());
return f;
}
if ((content.contains("<") && content.contains(">")) ||
(content.contains("[") && content.contains("]")))
{
String modifiedContent = content.replaceAll("[<>\\]\\[]", ",");
int index = 0;
while (!modifiedContent.equals(""))
{
String type = modifiedContent.substring(0, modifiedContent.indexOf(","));
if (!type.equals(""))
{
indexOfErrors.add(index);
typesList.add(type);
}
index = index + type.length() + 1;
modifiedContent = modifiedContent.substring(modifiedContent.indexOf(",") + 1);
if (!modifiedContent.contains(",") && !modifiedContent.equals(""))
{
indexOfErrors.add(index);
typesList.add(modifiedContent);
break;
}
}
return checkForTypeErrors(typesList, indexOfErrors, editor, rootPathMap);
}
if (content.contains("[") || content.contains("<") || content.contains("."))
{
f.complete(Collections.emptyList());
return f;
}
editor.withTypes(types -> {
if (types.containsKey(content))
{
f.complete(Collections.emptyList());
return;
}
final UnknownTypeError error = new UnknownTypeError(this, content, slot::setText, editor,
types.values().stream(), editor.getImportSuggestions().values().stream().
flatMap(Collection::stream)) {
};
error.recordPath(rootPathMap.locationFor(this));
f.complete(Arrays.asList(error));
});
return f;
}
| It checks for type errors and it returns a list of errors (wrapped as a Future).
| @param typesList the list of found types
| @param indexList the list of type indexes in the slot
| @param editor the editor of the class
| @param rootPathMap the root map from JavaFragment to XPath String identifying the location of that fragment.
| @return the Future list of errors
|
@OnThread(Tag.FXPlatform)
private Future> checkForTypeErrors(
ArrayList<String> typesList, ArrayList<Integer> indexList, InteractionManager editor,
LocationMap rootPathMap)
{
CompletableFuture<List<DirectSlotError>> f = new CompletableFuture<>();
ArrayList<DirectSlotError> listOfErrors = new ArrayList<>();
editor.withTypes(types -> {
int i = 0;
for (String t : typesList)
{
if (types.containsKey(t))
{
i = i + 1;
continue;
}
int startPosInSlot = indexList.get(i);
int endPosInSlot = startPosInSlot + t.length();
FXPlatformConsumer<String> replace = s -> slot.replace(startPosInSlot, endPosInSlot, false, s);
final UnknownTypeError error = new UnknownTypeError(this, t, replace, editor,
types.values().stream(), editor.getImportSuggestions().values().stream().
flatMap(Collection::stream));
error.recordPath(rootPathMap.locationFor(this));
listOfErrors.add(error);
i = i + 1;
}
f.complete(listOfErrors);
});
return f;
}
@Override
public TypeSlot getSlot()
{
return slot;
}
public void registerSlot(TypeSlot slot)
{
if (this.slot == null)
this.slot = slot;
}
}
top,
use,
map,
class TypeSlotFragment
. TypeSlotFragment
. TypeSlotFragment
. getVars
. getJavaCode
. findEarlyErrors
. findLateErrors
. checkForTypeErrors
. getSlot
. registerSlot
229 neLoCode
+ 6 LoComm