blob: f3f4c94780d9f85f47e7882a1e077e37c754e408 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 xored software, Inc. 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:
* xored software, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.dltk.core;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.declarations.ModuleDeclarationWrapper;
import org.eclipse.dltk.ast.parser.ASTCacheManager;
import org.eclipse.dltk.ast.parser.IASTCache;
import org.eclipse.dltk.ast.parser.IASTCache.ASTCacheEntry;
import org.eclipse.dltk.ast.parser.IModuleDeclaration;
import org.eclipse.dltk.ast.parser.ISourceParser;
import org.eclipse.dltk.compiler.CharOperation;
import org.eclipse.dltk.compiler.env.IModuleSource;
import org.eclipse.dltk.compiler.problem.IProblemReporter;
import org.eclipse.dltk.compiler.problem.ProblemCollector;
import org.eclipse.dltk.compiler.util.Util;
import org.eclipse.dltk.core.ISourceModuleInfoCache.ISourceModuleInfo;
import org.eclipse.dltk.core.RuntimePerformanceMonitor.PerformanceNode;
import org.eclipse.dltk.internal.core.ModelManager;
public class SourceParserUtil {
private static final String AST = "ast"; //$NON-NLS-1$
private static final String ERRORS = "errors"; //$NON-NLS-1$
private static boolean useASTCaching = true;
private static boolean useASTPersistenceCaching = true;
public static IModuleDeclaration parse(IModuleSource module,
String natureId, IProblemReporter reporter) {
final IModelElement element = module.getModelElement();
final ISourceParser parser = DLTKLanguageManager.getSourceParser(
element != null ? element.getScriptProject().getProject()
: null, natureId);
return parser.parse(module, reporter);
}
public static IModuleDeclaration parse(final ISourceModule module,
IProblemReporter reporter) {
final IDLTKLanguageToolkit toolkit = DLTKLanguageManager
.getLanguageToolkit(module);
if (toolkit == null) {
return null;
}
IModuleDeclaration moduleDeclaration = null;
PerformanceNode p1 = RuntimePerformanceMonitor.begin();
final String errorKey;
final String astKey;
final ISourceModuleInfo mifo = getCache().get(module);
if (mifo != null && useASTCaching) {
errorKey = getKey(ERRORS, 0);
astKey = getKey(AST, 0);
moduleDeclaration = (IModuleDeclaration) mifo.get(astKey);
if (moduleDeclaration != null) {
if (reporter != null) {
final ProblemCollector collector = (ProblemCollector) mifo
.get(errorKey);
if (collector != null) {
collector.copyTo(reporter);
}
}
}
if (moduleDeclaration == null && useASTPersistenceCaching) {
// Try to retrieve information from persistence cache.
IASTCache[] providers = ASTCacheManager.getProviders(toolkit
.getNatureId());
if (providers != null) {
for (IASTCache provider : providers) {
ASTCacheEntry restored = provider.restoreModule(module);
if (restored != null) {
if (reporter != null) {
if (restored.problems != null) {
restored.problems.copyTo(reporter);
}
}
// Store to local cache.
mifo.put(astKey, restored.module);
if (restored.problems != null
&& !restored.problems.isEmpty()) {
mifo.put(errorKey, restored.problems);
} else {
mifo.remove(errorKey);
}
moduleDeclaration = restored.module;
break;
}
}
}
}
} else {
errorKey = null;
astKey = null;
}
p1.done(toolkit.getNatureId(), "Retrive AST from cache", 0);
if (moduleDeclaration == null) {
p1.renew();
ISourceParser sourceParser = DLTKLanguageManager.getSourceParser(
module.getScriptProject().getProject(),
toolkit.getNatureId());
if (sourceParser != null) {
// if (sourceParser instanceof ISourceParserExtension) {
// ((ISourceParserExtension) sourceParser).setFlags(flags);
// }
final ProblemCollector collector = mifo != null ? new ProblemCollector()
: null;
final IModuleSource source;
if (module instanceof IModuleSource) {
source = (IModuleSource) module;
} else {
source = new IModuleSource() {
@Override
public String getFileName() {
return module.getPath().toString();
}
@Override
public String getSourceContents() {
try {
return module.getSource();
} catch (ModelException e) {
return Util.EMPTY_STRING;
}
}
@Override
public IModelElement getModelElement() {
return module;
}
@Override
public char[] getContentsAsCharArray() {
try {
return module.getSourceAsCharArray();
} catch (ModelException e) {
return CharOperation.NO_CHAR;
}
}
};
}
moduleDeclaration = sourceParser.parse(source,
collector != null ? collector : reporter);
if (collector != null && reporter != null) {
collector.copyTo(reporter);
}
p1.done(toolkit.getNatureId(), "AST parse time", 0);
if (moduleDeclaration != null && mifo != null && useASTCaching) {
mifo.put(astKey, moduleDeclaration);
if (useASTPersistenceCaching) {
// Store to persistence cache
IASTCache[] providers = ASTCacheManager
.getProviders(toolkit.getNatureId());
if (providers != null) {
for (IASTCache provider : providers) {
provider.storeModule(module, moduleDeclaration,
collector);
}
}
}
if (collector != null && !collector.isEmpty()) {
mifo.put(errorKey, collector);
} else {
mifo.remove(errorKey);
}
}
}
}
return moduleDeclaration;
}
public static ModuleDeclaration getModuleDeclaration(ISourceModule module) {
return getModuleDeclaration(module, null);
}
public static ModuleDeclaration getModuleDeclaration(ISourceModule module,
IProblemReporter reporter) {
return wrap(parse(module, reporter));
}
@Deprecated
public static ModuleDeclaration getModuleDeclaration(ISourceModule module,
IProblemReporter reporter, int flags) {
return getModuleDeclaration(module, reporter);
}
@Deprecated
public static ModuleDeclaration getModuleDeclaration(ISourceModule module,
IProblemReporter reporter, ISourceModuleInfo mifo) {
return getModuleDeclaration(module, reporter);
}
@Deprecated
public static ModuleDeclaration getModuleDeclaration(ISourceModule module,
IProblemReporter reporter, ISourceModuleInfo mifo, int flags) {
return getModuleDeclaration(module, reporter);
}
/**
* @param baseKey
* @param flags
* @return
*/
private static String getKey(String baseKey, int flags) {
return flags == 0 ? baseKey : baseKey + flags;
}
/**
* Parse the specified source
*
* @param module
* @param nature
* @param reporter
* @return
*/
public static ModuleDeclaration getModuleDeclaration(IModuleSource module,
String natureId, IProblemReporter reporter) {
final IModuleDeclaration result = parse(module, natureId, reporter);
return wrap(result);
}
private static ModuleDeclaration wrap(final IModuleDeclaration result) {
if (result != null) {
if (result instanceof ModuleDeclaration) {
return (ModuleDeclaration) result;
}
return new ModuleDeclarationWrapper(result);
} else {
return null;
}
}
/**
* This is for use in parsers.
*/
public static IModuleDeclaration getModuleFromCache(ISourceModuleInfo mifo,
IProblemReporter reporter) {
final int flags = 0;// FIXME remove later
if (mifo != null && useASTCaching) {
final IModuleDeclaration moduleDeclaration = (IModuleDeclaration) mifo
.get(getKey(AST, flags));
if (moduleDeclaration != null && reporter != null) {
final ProblemCollector collector = (ProblemCollector) mifo
.get(getKey(ERRORS, flags));
if (collector != null) {
collector.copyTo(reporter);
}
}
return moduleDeclaration;
}
return null;
}
public static void putModuleToCache(ISourceModuleInfo info,
IModuleDeclaration module, ProblemCollector collector) {
final int flags = 0; // TODO remove later
if (info != null && useASTCaching) {
info.put(getKey(AST, flags), module);
final String errorKey = getKey(ERRORS, flags);
if (collector != null && !collector.isEmpty()) {
info.put(errorKey, collector);
} else {
info.remove(errorKey);
}
}
}
/**
* Performance testing only
*/
public static void disableCache() {
useASTCaching = false;
}
public static void enableCache() {
useASTCaching = true;
}
public static void clearCache() {
getCache().clear();
}
public static ISourceModuleInfoCache getCache() {
return ModelManager.getModelManager().getSourceModuleInfoCache();
}
}