blob: 489f97817617fd86b06aec276d5870fed155fa56 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2014 Borland Software 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:
* Borland Software Corporation - initial API and implementation
* Christopher Gerking - bug 391289
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.editor.ui.completion;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.LinkedHashMap;
import java.util.Map;
import lpg.runtime.IPrsStream;
import lpg.runtime.IToken;
import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalEnvFactory;
import org.eclipse.m2m.internal.qvt.oml.ast.env.QvtOperationalFileEnv;
import org.eclipse.m2m.internal.qvt.oml.ast.parser.QvtOperationalVisitorCS;
import org.eclipse.m2m.internal.qvt.oml.common.MdaException;
import org.eclipse.m2m.internal.qvt.oml.compiler.QVTOCompiler;
import org.eclipse.m2m.internal.qvt.oml.compiler.QvtCompilerOptions;
import org.eclipse.m2m.internal.qvt.oml.compiler.UnitProxy;
import org.eclipse.m2m.internal.qvt.oml.cst.MappingModuleCS;
import org.eclipse.m2m.internal.qvt.oml.cst.UnitCS;
import org.eclipse.m2m.internal.qvt.oml.cst.parser.AbstractQVTParser;
import org.eclipse.m2m.internal.qvt.oml.cst.parser.QVTOLexer;
import org.eclipse.m2m.internal.qvt.oml.cst.parser.QVTOParser;
import org.eclipse.m2m.internal.qvt.oml.editor.ui.Activator;
import org.eclipse.m2m.internal.qvt.oml.editor.ui.completion.keywordhandler.IKeywordHandler;
import org.eclipse.m2m.internal.qvt.oml.editor.ui.completion.keywordhandler.KeywordHandlerRegistry;
import org.eclipse.m2m.internal.qvt.oml.emf.util.mmregistry.IMetamodelRegistryProvider;
import org.eclipse.ocl.OCLInput;
import org.eclipse.ocl.ParserException;
import org.eclipse.ocl.cst.CSTNode;
import org.eclipse.ocl.lpg.AbstractLexer;
/**
* @author aigdalov
* Created on Oct 30, 2007
*/
public class QvtCompletionCompiler extends QVTOCompiler {
private final QvtCompletionData myData;
private final Map<URI, CFileData> myCFileDataMap = new LinkedHashMap<URI, CFileData>();
private QvtOperationalEnv myEnvironment;
public QvtCompletionCompiler(IMetamodelRegistryProvider metamodelProvider, QvtCompletionData data) {
super(metamodelProvider);
myData = data;
}
public Map<URI, CFileData> getCFileDataMap() {
return myCFileDataMap;
}
public AbstractLexer createLexer(UnitProxy unit) throws IOException, ParserException, BadLocationException {
CFileData cFileData = getCFileData(unit.getURI());
if (cFileData.getLexer() != null) {
return cFileData.getLexer();
}
Reader reader = createReader(unit);
QVTOLexer lexer = new QVTOLexer(new QvtOperationalEnvFactory(
getEPackageRegistry(unit.getURI())).createEnvironment(unit.getURI()));
cFileData.setLexer(lexer);
try {
lexer.reset(new OCLInput(reader).getContent(), unit.getURI().lastSegment());
QVTOParser qvtoParser = new QVTOParser(lexer);
lexer.lexer(qvtoParser.getIPrsStream());
cFileData.setParser(qvtoParser);
} finally {
reader.close();
}
return lexer;
}
@Override
protected Reader createReader(UnitProxy source) throws IOException {
if (source.getURI().equals(myData.getCFile().getURI())) {
String documentText = myData.getDocument().get();
return new StringReader(documentText);
}
return super.createReader(source);
}
public QvtOperationalEnv compileAll() {
if (myEnvironment == null) {
URI uri = this.myData.getCFile().getURI();
myEnvironment = new QvtOperationalEnvFactory(getEPackageRegistry(uri)).createEnvironment(uri);
QvtCompilerOptions options = new QvtCompilerOptions();
options.setReportErrors(false);
options.setShowAnnotations(false);
options.setSourceLineNumbersEnabled(false);
try {
compile(myData.getCFile(), options, null);
} catch (MdaException ex) {
Activator.log(ex);
}
}
return myEnvironment;
}
@Override
protected QvtOperationalVisitorCS createAnalyzer(AbstractQVTParser parser, QvtCompilerOptions options, Monitor monitor) {
return new QvtCompletionVisitorCS(parser, options, monitor) {
@Override
protected void setEnv(QvtOperationalEnv env) {
super.setEnv(env);
myEnvironment = env;
}
};
}
@Override
protected CSTParseResult parse(UnitProxy source, QvtCompilerOptions options) throws ParserException {
CFileData cFileData = compile(source);
AbstractQVTParser qvtParser = cFileData.getParser();
UnitCS unitCS = cFileData.getUnitCS();
QvtOperationalFileEnv env = (QvtOperationalFileEnv)cFileData.getLexer().getEnvironment();
CSTParseResult result = new CSTParseResult();
result.unitCS = unitCS;
result.env = env;
result.parser = qvtParser;
return result;
}
private CFileData compile(UnitProxy cFile) {
CFileData cFileData = getCFileData(cFile.getURI());
try {
AbstractLexer lexer = createLexer(cFile);
IPrsStream prsStream = lexer.getILexStream().getIPrsStream();
IKeywordHandler[] keywordHandlers = KeywordHandlerRegistry.getInstance().getKeywordHandlers();
StringBuilder lightweightScriptBuilder = new StringBuilder(lexer.getILexStream().getStreamLength());
for (int i = 0, n = prsStream.getSize(); i < n; i++) {
IToken token = prsStream.getTokenAt(i);
for (IKeywordHandler keywordHandler : keywordHandlers) {
String contribution = keywordHandler.handle(token, prsStream, myData, cFileData);
if (contribution != null) {
int offsetDelta = token.getStartOffset() - lightweightScriptBuilder.length();
for (int j = 0; j < offsetDelta - 1; j++) {
lightweightScriptBuilder.append(' ');
}
lightweightScriptBuilder.append(contribution);
break;
}
}
}
String lightweightScript = lightweightScriptBuilder.toString();
cFileData.setLightweightScript(lightweightScript);
CSTNode cstNode = LightweightParserUtil.parse(lightweightScript, cFile, LightweightParserUtil.ParserTypeEnum.LIGHTWEIGHT_PARSER);
cFileData.setUnitCS((UnitCS)cstNode);
} catch (Exception ex) {
Activator.log(ex);
}
return cFileData;
}
public CFileData getCFileData(URI unitURI) {
CFileData cFileData = myCFileDataMap.get(unitURI);
if (cFileData == null) {
cFileData = new CFileData();
myCFileDataMap.put(unitURI, cFileData);
}
return cFileData;
}
public CFileData getCFileData(MappingModuleCS mappingModuleCS) {
for (CFileData cFileData : myCFileDataMap.values()) {
UnitCS unitCS = cFileData.getUnitCS();
if(unitCS != null && unitCS.getModules().contains(mappingModuleCS)) {
return cFileData;
}
}
return null;
}
}