/*******************************************************************************
* Copyright © 2011, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.gen.java;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.edt.compiler.core.IEGLConstants;
import org.eclipse.edt.gen.AbstractGeneratorCommand;
import org.eclipse.edt.gen.EglContext;
import org.eclipse.edt.gen.EGLMessages.EGLMessage;
import org.eclipse.edt.mof.codegen.api.TabbedWriter;
import org.eclipse.edt.mof.codegen.api.TemplateContext;
import org.eclipse.edt.mof.egl.Annotation;
import org.eclipse.edt.mof.egl.Element;
import org.eclipse.edt.mof.egl.Expression;
import org.eclipse.edt.mof.egl.FunctionMember;
import org.eclipse.edt.mof.egl.Statement;
import org.eclipse.edt.mof.egl.Type;
public class Context extends EglContext {
private static final long serialVersionUID = 6429116299734843162L;
private TabbedWriter tabbedWriter;
private boolean smapIsProcessing;
private boolean smapHasOutstandingLine;
private int firstEglLineNumber;
private int lastEglLineNumber;
private int firstJavaLineNumber;
private int lastJavaLineNumber;
private int smapStatementLevel;
private FunctionMember currentFunction;
private String currentFile;
private String smapPreviousLine = "";
private int smapPreviousEglLineNumber;
private int smapPreviousJavaLineNumber;
private StringBuffer smapData = new StringBuffer();
private StringBuffer smapExtension = new StringBuffer();
private List<String> smapFiles = new ArrayList<String>();
public Context(AbstractGeneratorCommand processor) {
super(processor);
smapData.append(Constants.smap_header);
smapExtension.append("");
}
public TabbedWriter getTabbedWriter() {
if (tabbedWriter == null) {
tabbedWriter = Boolean.TRUE.equals(getParameter(org.eclipse.edt.gen.Constants.parameter_report)) ? new JavaTabbedReportWriter(this,
"org.eclipse.edt.gen.java.templates.", new StringWriter()) : new JavaTabbedWriter(this, new StringWriter());
return tabbedWriter;
} else {
TabbedWriter newTabbedWriter = new JavaTabbedWriter(this, new StringWriter());
newTabbedWriter.setLineNumber(tabbedWriter.getLineNumber());
return newTabbedWriter;
}
}
public FunctionMember getCurrentFunction() {
return currentFunction;
}
public void setCurrentFunction(FunctionMember currentFunction) {
this.currentFunction = currentFunction;
}
public String getCurrentFile() {
return currentFile;
}
public void setCurrentFile(String currentFile) {
this.currentFile = currentFile;
}
public StringBuffer getSmapData() {
return smapData;
}
public StringBuffer getSmapExtension() {
return smapExtension;
}
public List<String> getSmapFiles() {
return smapFiles;
}
public boolean isSmapIsProcessing() {
return smapIsProcessing;
}
public void setSmapIsProcessing(boolean smapIsProcessing) {
this.smapIsProcessing = smapIsProcessing;
}
public String getRawPrimitiveMapping(String item) {
return super.getPrimitiveMapping(item);
}
@SuppressWarnings("unchecked")
public String getPrimitiveMapping(String item) {
String value = super.getPrimitiveMapping(item);
if (value != null) {
// check to see if this is in the list of imported types. If it is, then we can use the short name.
List<String> typesImported = (List<String>) this.getAttribute(this.getClass(), Constants.SubKey_partTypesImported);
for (String imported : typesImported) {
if (value.equalsIgnoreCase(imported)) {
// it was is the table, so use the short name
if (value.indexOf('.') >= 0)
value = value.substring(value.lastIndexOf('.') + 1);
break;
}
}
}
return value;
}
public String getRawPrimitiveMapping(Type type) {
return super.getPrimitiveMapping(type);
}
@SuppressWarnings("unchecked")
public String getPrimitiveMapping(Type type) {
String value = super.getPrimitiveMapping(type);
if (value != null) {
// check to see if this is in the list of imported types. If it is, then we can use the short name.
List<String> typesImported = (List<String>) this.getAttribute(this.getClass(), Constants.SubKey_partTypesImported);
for (String imported : typesImported) {
if (value.equalsIgnoreCase(imported)) {
// it was is the table, so use the short name
if (value.indexOf('.') >= 0)
value = value.substring(value.lastIndexOf('.') + 1);
break;
}
}
}
return value;
}
public String getRawNativeImplementationMapping(Type type) {
return super.getNativeImplementationMapping(type);
}
@SuppressWarnings("unchecked")
public String getNativeImplementationMapping(Type type) {
String value = super.getNativeImplementationMapping(type);
// check to see if this is in the list of imported types. If it is, then we can use the short name.
List<String> typesImported = (List<String>) this.getAttribute(this.getClass(), Constants.SubKey_partTypesImported);
for (String imported : typesImported) {
if (value.equalsIgnoreCase(imported)) {
// it was is the table, so use the short name
if (value.indexOf('.') >= 0)
value = value.substring(value.lastIndexOf('.') + 1);
break;
}
}
return value;
}
public String getRawNativeInterfaceMapping(Type type) {
return super.getNativeInterfaceMapping(type);
}
@SuppressWarnings("unchecked")
public String getNativeInterfaceMapping(Type type) {
String value = super.getNativeInterfaceMapping(type);
// check to see if this is in the list of imported types. If it is, then we can use the short name.
List<String> typesImported = (List<String>) this.getAttribute(this.getClass(), Constants.SubKey_partTypesImported);
for (String imported : typesImported) {
if (value.equalsIgnoreCase(imported)) {
// it was is the table, so use the short name
if (value.indexOf('.') >= 0)
value = value.substring(value.lastIndexOf('.') + 1);
break;
}
}
return value;
}
public void invoke(String genMethod, Expression object, TemplateContext ctx, TabbedWriter out) {
// is this the first time into an expression group
Annotation annotation = object.getAnnotation(IEGLConstants.EGL_LOCATION);
if (!smapIsProcessing && annotation != null && annotation.getValue(IEGLConstants.EGL_PARTLINE) != null) {
smapIsProcessing = true;
int thisEglLineNumber = ((Integer) annotation.getValue(IEGLConstants.EGL_PARTLINE)).intValue();
// check to see if this is logically part of an existing statement and if so, then use that number instead
if (object.getAnnotation(IEGLConstants.EGL_STATEMENTLOCATION) != null) {
Annotation relatedAnnotation = object.getAnnotation(IEGLConstants.EGL_STATEMENTLOCATION);
if (relatedAnnotation.getValue() != null && relatedAnnotation.getValue() instanceof Annotation) {
if (((Annotation) relatedAnnotation.getValue()).getValue(IEGLConstants.EGL_PARTLINE) != null)
thisEglLineNumber = ((Integer) ((Annotation) relatedAnnotation.getValue()).getValue(IEGLConstants.EGL_PARTLINE)).intValue();
}
}
// if we are continuing the same egl line, then skip writing out debug data
if (thisEglLineNumber != lastEglLineNumber) {
// if there is an outstanding line, write it
writeSmapLine();
smapHasOutstandingLine = true;
firstEglLineNumber = thisEglLineNumber;
lastEglLineNumber = thisEglLineNumber;
firstJavaLineNumber = out.getLineNumber();
}
// process the generation
super.invoke(genMethod, object, ctx, out);
// if we had some statements as part of this expression, then we already have the corrected ending line number
if (lastJavaLineNumber == 0)
lastJavaLineNumber = out.getLineNumber();
smapIsProcessing = false;
} else {
if (smapIsProcessing && annotation != null && annotation.getValue(IEGLConstants.EGL_PARTLINE) != null)
lastEglLineNumber = ((Integer) annotation.getValue(IEGLConstants.EGL_PARTLINE)).intValue();
// process the generation
super.invoke(genMethod, object, ctx, out);
if (smapIsProcessing)
lastJavaLineNumber = out.getLineNumber();
}
}
public void invoke(String genMethod, Statement object, TemplateContext ctx, TabbedWriter out) {
// for statements, we only want to collect the data if this statement is part of a larger expression
if (smapIsProcessing) {
Annotation annotation = object.getAnnotation(IEGLConstants.EGL_LOCATION);
if (annotation != null && annotation.getValue(IEGLConstants.EGL_PARTLINE) != null)
lastEglLineNumber = ((Integer) annotation.getValue(IEGLConstants.EGL_PARTLINE)).intValue();
// process the generation
super.invoke(genMethod, object, ctx, out);
// the last line is 1 less because this is a statement
lastJavaLineNumber = out.getLineNumber() - 1;
if (firstJavaLineNumber > lastJavaLineNumber)
lastJavaLineNumber = firstJavaLineNumber;
} else
// process the generation
super.invoke(genMethod, object, ctx, out);
}
public void genSmapEnd(Element object, TabbedWriter out) {
// is this the first time into an expression group
Annotation annotation = object.getAnnotation(IEGLConstants.EGL_LOCATION);
if (annotation != null && annotation.getValue(IEGLConstants.EGL_PARTLINE) != null) {
int thisEglLineNumber = ((Integer) annotation.getValue(IEGLConstants.EGL_PARTLINE)).intValue();
// if there is an outstanding line, write it
writeSmapLine();
smapHasOutstandingLine = true;
firstEglLineNumber = thisEglLineNumber;
lastEglLineNumber = thisEglLineNumber;
firstJavaLineNumber = out.getLineNumber();
lastJavaLineNumber = out.getLineNumber();
smapIsProcessing = false;
}
}
public void setSmapLastJavaLineNumber(int number) {
lastJavaLineNumber = number;
}
public void adjustSmapStatementLevel(int number) {
smapStatementLevel += number;
}
public int getSmapStatementLevel() {
return smapStatementLevel;
}
public void writeSmapLine() {
if (smapHasOutstandingLine) {
// is there really a continuation of a previous line
if (smapPreviousEglLineNumber == firstEglLineNumber) {
// we need to rewrite the previous line with the new boundaries
smapData.delete(smapData.length() - smapPreviousLine.length(), smapData.length() + 1);
// now set up the correct range
firstJavaLineNumber = smapPreviousJavaLineNumber;
}
smapPreviousLine = "" + firstEglLineNumber;
if (currentFile != null) {
if (smapFiles.indexOf(currentFile) < 0)
smapFiles.add(currentFile);
smapPreviousLine += "#" + (smapFiles.indexOf(currentFile) + 1);
} else
smapPreviousLine += "#1";
smapPreviousLine += ":" + firstJavaLineNumber;
if (firstJavaLineNumber != lastJavaLineNumber)
smapPreviousLine += "," + (lastJavaLineNumber - firstJavaLineNumber + 1);
smapPreviousLine += "\n";
smapData.append(smapPreviousLine);
// remember the details
smapPreviousEglLineNumber = firstEglLineNumber;
smapPreviousJavaLineNumber = firstJavaLineNumber;
// we need to reset the last java line number
lastJavaLineNumber = 0;
}
smapHasOutstandingLine = false;
}
public void handleValidationError(Element obj) {
String[] details = new String[] { obj.getEClass().getETypeSignature() };
EGLMessage message = EGLMessage.createEGLMessage(getMessageMapping(), EGLMessage.EGL_ERROR_MESSAGE, Constants.EGLMESSAGE_MISSING_TEMPLATE_FOR_OBJECT,
obj, details, obj.getAnnotation(IEGLConstants.EGL_LOCATION));
getMessageRequestor().addMessage(message);
}
public void handleValidationError(Annotation obj) {
String[] details = new String[] { obj.getEClass().getETypeSignature() };
EGLMessage message = EGLMessage.createEGLMessage(getMessageMapping(), EGLMessage.EGL_ERROR_MESSAGE,
Constants.EGLMESSAGE_MISSING_TEMPLATE_FOR_ANNOTATION, obj, details, getLastStatementLocation());
getMessageRequestor().addMessage(message);
}
public void handleValidationError(Type obj) {
String[] details = new String[] { obj.getEClass().getETypeSignature() };
EGLMessage message = EGLMessage.createEGLMessage(getMessageMapping(), EGLMessage.EGL_ERROR_MESSAGE, Constants.EGLMESSAGE_MISSING_TEMPLATE_FOR_TYPE,
obj, details, getLastStatementLocation());
getMessageRequestor().addMessage(message);
}
}