Generic Method inserts.

This commit is contained in:
Michael Uhl 2019-07-26 10:18:50 +02:00
parent 809459f6e9
commit ab664efb6b

View File

@ -1,176 +1,180 @@
package typinferenzplugin;
import static org.eclipse.core.runtime.IStatus.ERROR;
import static typinferenzplugin.Activator.PLUGIN_ID;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;
import org.apache.commons.io.output.NullOutputStream;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.Status;
import de.dhbwstuttgart.bytecode.BytecodeGen;
import de.dhbwstuttgart.bytecode.Exception.BytecodeGeneratorError;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typedeployment.TypeInsert;
import de.dhbwstuttgart.typedeployment.TypeInsertFactory;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import de.dhbwstuttgart.typeinference.unify.UnifyResultListener;
import de.dhbwstuttgart.typeinference.unify.UnifyResultModel;
import typinferenzplugin.editor.JavEditor;
import typinferenzplugin.error.ErrorOutput;
public class Typinferenz {
private static final ILog LOG = Activator.getDefault().getLog();
private JavEditor editor;
private SourceFile parsedSource;
private JavaTXCompiler compiler;
private List<ResultSet> tiResults = new ArrayList<>();
private Set<ResultSet> forByteCode = new HashSet<>();
public Typinferenz(JavEditor forEditor) {
this.editor = forEditor;
}
public UnifyResultModel run(UnifyResultListener resultListener) throws TypeinferenceException {
try {
compiler = new JavaTXCompiler(editor.getFilePath().toFile(), false);
SourceFile parsedSourceOrNull = compiler.sourceFiles.get(editor.getFilePath().toFile());
if (parsedSourceOrNull != null) {
this.parsedSource = parsedSourceOrNull;
}
return compiler.typeInferenceAsync(resultListener, new OutputStreamWriter(new NullOutputStream()));
} catch (ClassNotFoundException e) {
LOG.log(new Status(ERROR, PLUGIN_ID, e.getMessage(), e));
} catch (IOException e) {
LOG.log(new Status(ERROR, PLUGIN_ID, e.getMessage(), e));
}
return null;
}
public Collection<ResultSet> getResultSets() {
return this.forByteCode;
}
public Vector<JavMarker> updateWithResult(Vector<JavMarker> ret, List<ResultSet> newResults) {
this.tiResults.addAll(newResults);
this.forByteCode.addAll(newResults);
Set<TypeInsert> tips = new HashSet<>();
for (ResultSet tiResult : newResults) {
tips.addAll(TypeInsertFactory.createTypeInsertPoints(parsedSource, tiResult));
for (TypeInsert p : tips) {
TypeReplaceMarker toAdd = new TypeReplaceMarker(editor, tiResult, p);
if (!ret.contains(toAdd)) {
ret.add(toAdd);
} else {
//LOG.log(new Status(ERROR, PLUGIN_ID, "Marker bereits vorhanden: " + toAdd.toString()));
}
}
}
String outputDirectory = getOutputDirectory();
if (this.forByteCode.size() > 0) {
for (SourceFile sf : compiler.sourceFiles.values()) {
try {
HashMap<String, byte[]> bytecode = getBytecode(sf, this.forByteCode, outputDirectory);
this.writeClassFile(outputDirectory, bytecode);
} catch (BytecodeGeneratorError ex) {
ErrorMarker toAdd = new ErrorMarker(ex.getMessage(), new CodePoint(sf.getOffset()));
ret.add(toAdd);
}
}
}
return ret;
}
public String getOutputDirectory() {
String outputDirectory = editor.getFilePath().toString();
outputDirectory = outputDirectory.substring(0,
outputDirectory.length() - editor.getFilePath().lastSegment().length());// ".jav" hat Länge 4
return outputDirectory;
}
public void updateresultSets(Vector<ResultSet> typeInsertResults) {
//this.tiResults = typeInsertResults;
// for (ResultSet resultSet : typeInsertResults) {
// for (ResultPair<RefTypeOrTPHOrWildcardOrGeneric, RefTypeOrTPHOrWildcardOrGeneric> result : resultSet.results) {
// LOG.log(new Status(INFO, PLUGIN_ID, "Types: " + result.getRight().getClass().getCanonicalName() + "," + result.getLeft().getClass().getCanonicalName()));
// LOG.log(new Status(INFO, PLUGIN_ID, "Values: " + result.getRight() + "," + result.getLeft()));
// System.out.println(result.getRight() + "," + result.getLeft());
// }
// }
}
public Set<String> resolve(RefTypeOrTPHOrWildcardOrGeneric tph) throws TypeinferenceException {
Set<String> ret = new TreeSet<>();
try {
for (ResultSet tiResult : tiResults) {
ret.add(tiResult.resolveType(tph).resolvedType.acceptTV(new TypeToDescriptor()));
}
} catch (TypeinferenceException texc) {
throw texc; // Die aufrufende Instanz sollte daraus dann einen ErrorMarker generieren.
} catch (Exception exc) {
exc.printStackTrace(); // Hier wird kein Marker generiert... nur Debug-Output
new ErrorOutput("Fehler beim Parsen und Inferieren");
}
return ret;
}
public synchronized HashMap<String, byte[]> getBytecode(SourceFile sf, Collection<ResultSet> resultSets, String path) {
HashMap<String, byte[]> classFiles = new HashMap<>();
BytecodeGen bytecodeGen = new BytecodeGen(classFiles, resultSets, sf, path);
bytecodeGen.visit(sf);
return bytecodeGen.getClassFiles();
}
public void writeClassFile(String outputDirectory, HashMap<String, byte[]> classFiles) {
FileOutputStream output;
for (String name : classFiles.keySet()) {
byte[] bytecode = classFiles.get(name);
try {
System.out.println("generating" + name + ".class file");
// output = new FileOutputStream(new File(System.getProperty("user.dir") +
// "/testBytecode/generatedBC/" +name+".class"));
output = new FileOutputStream(new File(outputDirectory + name + ".class"));
output.write(bytecode);
output.close();
System.out.println(name + ".class file generated");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public SourceFile getSourceFile() {
return parsedSource;
}
}
package typinferenzplugin;
import static org.eclipse.core.runtime.IStatus.ERROR;
import static typinferenzplugin.Activator.PLUGIN_ID;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;
import org.apache.commons.io.output.NullOutputStream;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.Status;
import de.dhbwstuttgart.bytecode.BytecodeGen;
import de.dhbwstuttgart.bytecode.Exception.BytecodeGeneratorError;
import de.dhbwstuttgart.bytecode.descriptor.TypeToDescriptor;
import de.dhbwstuttgart.bytecode.utilities.SimplifyResult;
import de.dhbwstuttgart.core.JavaTXCompiler;
import de.dhbwstuttgart.exceptions.TypeinferenceException;
import de.dhbwstuttgart.syntaxtree.SourceFile;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typedeployment.TypeInsert;
import de.dhbwstuttgart.typedeployment.TypeInsertFactory;
import de.dhbwstuttgart.typeinference.result.ResultSet;
import de.dhbwstuttgart.typeinference.unify.UnifyResultListener;
import de.dhbwstuttgart.typeinference.unify.UnifyResultModel;
import typinferenzplugin.editor.JavEditor;
import typinferenzplugin.error.ErrorOutput;
public class Typinferenz {
private static final ILog LOG = Activator.getDefault().getLog();
private JavEditor editor;
private SourceFile parsedSource;
private JavaTXCompiler compiler;
private List<ResultSet> tiResults = new ArrayList<>();
private Set<ResultSet> forByteCode = new HashSet<>();
public Typinferenz(JavEditor forEditor) {
this.editor = forEditor;
}
public UnifyResultModel run(UnifyResultListener resultListener) throws TypeinferenceException {
try {
compiler = new JavaTXCompiler(editor.getFilePath().toFile(), false);
SourceFile parsedSourceOrNull = compiler.sourceFiles.get(editor.getFilePath().toFile());
if (parsedSourceOrNull != null) {
this.parsedSource = parsedSourceOrNull;
}
return compiler.typeInferenceAsync(resultListener, new OutputStreamWriter(new NullOutputStream()));
} catch (ClassNotFoundException e) {
LOG.log(new Status(ERROR, PLUGIN_ID, e.getMessage(), e));
} catch (IOException e) {
LOG.log(new Status(ERROR, PLUGIN_ID, e.getMessage(), e));
}
return null;
}
public Collection<ResultSet> getResultSets() {
return this.forByteCode;
}
public Vector<JavMarker> updateWithResult(Vector<JavMarker> ret, List<ResultSet> newResults) {
this.tiResults.addAll(newResults);
this.forByteCode.addAll(newResults);
Set<TypeInsert> tips = new HashSet<>();
String outputDirectory = getOutputDirectory();
if (this.forByteCode.size() > 0) {
for (SourceFile sf : compiler.sourceFiles.values()) {
try {
HashMap<String, byte[]> bytecode = getBytecode(sf, this.forByteCode, outputDirectory);
compiler.generateBytecodForFile(outputDirectory, bytecode, sf, new ArrayList<>(forByteCode));
this.writeClassFile(outputDirectory, bytecode);
} catch (BytecodeGeneratorError | IOException ex) {
ErrorMarker toAdd = new ErrorMarker(ex.getMessage(), new CodePoint(sf.getOffset()));
ret.add(toAdd);
}
}
}
for (ResultSet tiResult : newResults) {
tips.addAll(TypeInsertFactory.createTypeInsertPoints(parsedSource, tiResult));
for (TypeInsert p : tips) {
TypeReplaceMarker toAdd = new TypeReplaceMarker(editor, tiResult, p);
if (!ret.contains(toAdd)) {
ret.add(toAdd);
} else {
//LOG.log(new Status(ERROR, PLUGIN_ID, "Marker bereits vorhanden: " + toAdd.toString()));
}
}
}
return ret;
}
public String getOutputDirectory() {
String outputDirectory = editor.getFilePath().toString();
outputDirectory = outputDirectory.substring(0,
outputDirectory.length() - editor.getFilePath().lastSegment().length());// ".jav" hat Länge 4
return outputDirectory;
}
public void updateresultSets(Vector<ResultSet> typeInsertResults) {
//this.tiResults = typeInsertResults;
// for (ResultSet resultSet : typeInsertResults) {
// for (ResultPair<RefTypeOrTPHOrWildcardOrGeneric, RefTypeOrTPHOrWildcardOrGeneric> result : resultSet.results) {
// LOG.log(new Status(INFO, PLUGIN_ID, "Types: " + result.getRight().getClass().getCanonicalName() + "," + result.getLeft().getClass().getCanonicalName()));
// LOG.log(new Status(INFO, PLUGIN_ID, "Values: " + result.getRight() + "," + result.getLeft()));
// System.out.println(result.getRight() + "," + result.getLeft());
// }
// }
}
public Set<String> resolve(RefTypeOrTPHOrWildcardOrGeneric tph) throws TypeinferenceException {
Set<String> ret = new TreeSet<>();
try {
for (ResultSet tiResult : tiResults) {
ret.add(tiResult.resolveType(tph).resolvedType.acceptTV(new TypeToDescriptor()));
}
} catch (TypeinferenceException texc) {
throw texc; // Die aufrufende Instanz sollte daraus dann einen ErrorMarker generieren.
} catch (Exception exc) {
exc.printStackTrace(); // Hier wird kein Marker generiert... nur Debug-Output
new ErrorOutput("Fehler beim Parsen und Inferieren");
}
return ret;
}
public synchronized HashMap<String, byte[]> getBytecode(SourceFile sf, Collection<ResultSet> resultSets, String path) {
HashMap<String, byte[]> classFiles = new HashMap<>();
BytecodeGen bytecodeGen = new BytecodeGen(classFiles, resultSets, sf, path);
bytecodeGen.visit(sf);
List<HashMap<String, SimplifyResult>> simplifyResultsList = bytecodeGen.getSimplifyResultsList();
return bytecodeGen.getClassFiles();
}
public void writeClassFile(String outputDirectory, HashMap<String, byte[]> classFiles) {
FileOutputStream output;
for (String name : classFiles.keySet()) {
byte[] bytecode = classFiles.get(name);
try {
System.out.println("generating" + name + ".class file");
// output = new FileOutputStream(new File(System.getProperty("user.dir") +
// "/testBytecode/generatedBC/" +name+".class"));
output = new FileOutputStream(new File(outputDirectory + name + ".class"));
output.write(bytecode);
output.close();
System.out.println(name + ".class file generated");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public SourceFile getSourceFile() {
return parsedSource;
}
}