blob: f133f264aa307e3aa5045b439fc35fb4d39a98d2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2013 Sierra Wireless 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:
* Sierra Wireless - initial API and implementation
*******************************************************************************/
package org.eclipse.ldt.core.internal.ast.models;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.ASTVisitor;
import org.eclipse.dltk.core.IScriptFolder;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.ldt.core.IProjectSourceVisitor2;
import org.eclipse.ldt.core.LuaUtils;
import org.eclipse.ldt.core.LuaUtils.ProjectFragmentFilter;
import org.eclipse.ldt.core.internal.Activator;
import org.eclipse.ldt.core.internal.LuaLanguageToolkit;
import org.eclipse.ldt.core.internal.PreferenceInitializer;
import org.eclipse.ldt.core.internal.ast.models.api.ExprTypeRef;
import org.eclipse.ldt.core.internal.ast.models.api.ExternalTypeRef;
import org.eclipse.ldt.core.internal.ast.models.api.FunctionTypeDef;
import org.eclipse.ldt.core.internal.ast.models.api.InlineTypeRef;
import org.eclipse.ldt.core.internal.ast.models.api.InternalTypeRef;
import org.eclipse.ldt.core.internal.ast.models.api.Item;
import org.eclipse.ldt.core.internal.ast.models.api.LuaFileAPI;
import org.eclipse.ldt.core.internal.ast.models.api.ModuleTypeRef;
import org.eclipse.ldt.core.internal.ast.models.api.PrimitiveTypeRef;
import org.eclipse.ldt.core.internal.ast.models.api.RecordTypeDef;
import org.eclipse.ldt.core.internal.ast.models.api.Return;
import org.eclipse.ldt.core.internal.ast.models.api.TypeDef;
import org.eclipse.ldt.core.internal.ast.models.api.TypeRef;
import org.eclipse.ldt.core.internal.ast.models.api.UnknownItem;
import org.eclipse.ldt.core.internal.ast.models.common.LuaASTNode;
import org.eclipse.ldt.core.internal.ast.models.common.LuaSourceRoot;
import org.eclipse.ldt.core.internal.ast.models.file.Block;
import org.eclipse.ldt.core.internal.ast.models.file.Call;
import org.eclipse.ldt.core.internal.ast.models.file.Identifier;
import org.eclipse.ldt.core.internal.ast.models.file.Index;
import org.eclipse.ldt.core.internal.ast.models.file.Invoke;
import org.eclipse.ldt.core.internal.ast.models.file.LocalVar;
import org.eclipse.ldt.core.internal.ast.models.file.LuaExpression;
import org.eclipse.ldt.core.internal.ast.models.file.LuaInternalContent;
public final class LuaASTUtils {
private LuaASTUtils() {
}
private static class ClosestItemVisitor extends ASTVisitor {
private Item result = null;
private int position;
private String identifierName;
public ClosestItemVisitor(int position, String identifierName) {
super();
this.position = position;
this.identifierName = identifierName;
}
public Item getResult() {
return result;
}
@Override
public boolean visit(ASTNode node) throws Exception {
if (node instanceof LocalVar)
return false;
// we go down util we found the closer block.
if (node instanceof Block) {
if (node.sourceStart() <= position && position <= node.sourceEnd()) {
return true;
}
return false;
}
return false;
}
@Override
public boolean endvisit(ASTNode node) throws Exception {
if (result == null && node instanceof Block) {
// we go up only on the parent block
List<LocalVar> localVars = ((Block) node).getLocalVars();
for (LocalVar localVar : localVars) {
Item item = localVar.getVar();
if (item.getName().equals(identifierName)) {
result = item;
}
}
return true;
}
return false;
}
};
public static Item getClosestLocalVar(final LuaSourceRoot luaSourceRoot, final String identifierName, final int position) {
// traverse the root block on the file with this visitor
try {
ClosestItemVisitor closestItemVisitor = new ClosestItemVisitor(position, identifierName);
luaSourceRoot.getInternalContent().getContent().traverse(closestItemVisitor);
return closestItemVisitor.getResult();
// CHECKSTYLE:OFF
} catch (Exception e) {
// CHECKSTYLE:ON
Activator.logError("unable to collect local var", e); //$NON-NLS-1$
}
return null;
}
public static TypeResolution resolveType(ISourceModule sourceModule, TypeRef typeRef) {
if (typeRef instanceof PrimitiveTypeRef) {
return resolveType(sourceModule, (PrimitiveTypeRef) typeRef);
}
if (typeRef instanceof InternalTypeRef) {
return resolveType(sourceModule, (InternalTypeRef) typeRef);
}
if (typeRef instanceof ExternalTypeRef) {
return resolveType(sourceModule, (ExternalTypeRef) typeRef);
}
if (typeRef instanceof ModuleTypeRef) {
return resolveType(sourceModule, (ModuleTypeRef) typeRef);
}
if (typeRef instanceof ExprTypeRef) {
return resolveType(sourceModule, (ExprTypeRef) typeRef);
}
if (typeRef instanceof InlineTypeRef) {
return resolveType(sourceModule, (InlineTypeRef) typeRef);
}
return null;
}
public static TypeResolution resolveType(ISourceModule sourceModule, PrimitiveTypeRef primitiveTypeRef) {
// matching the primitive type #string to string#string if any
if (primitiveTypeRef.getTypeName().equals("string")) { //$NON-NLS-1$
ISourceModule stringSourceModule = LuaUtils.getSourceModule("string", sourceModule.getScriptProject()); //$NON-NLS-1$
if (stringSourceModule == null)
return null;
LuaSourceRoot luaSourceRoot = LuaASTModelUtils.getLuaSourceRoot(stringSourceModule);
TypeDef typeDef = luaSourceRoot.getFileapi().getTypes().get("string"); //$NON-NLS-1$
return new TypeResolution(stringSourceModule, typeDef);
}
return null;
}
public static TypeResolution resolveType(ISourceModule sourceModule, InternalTypeRef internalTypeRef) {
LuaSourceRoot luaSourceRoot = LuaASTModelUtils.getLuaSourceRoot(sourceModule);
TypeDef typeDef = luaSourceRoot.getFileapi().getTypes().get(internalTypeRef.getTypeName());
return new TypeResolution(sourceModule, typeDef);
}
public static TypeResolution resolveType(ISourceModule sourceModule, ExternalTypeRef externalTypeRef) {
ISourceModule externalSourceModule = LuaUtils.getSourceModule(externalTypeRef.getModuleName(), sourceModule.getScriptProject());
if (externalSourceModule == null)
return null;
LuaSourceRoot luaSourceRoot = LuaASTModelUtils.getLuaSourceRoot(externalSourceModule);
TypeDef typeDef = luaSourceRoot.getFileapi().getTypes().get(externalTypeRef.getTypeName());
return new TypeResolution(externalSourceModule, typeDef);
}
public static TypeResolution resolveType(ISourceModule sourceModule, ModuleTypeRef moduleTypeRef) {
ISourceModule referencedSourceModule = LuaUtils.getSourceModule(moduleTypeRef.getModuleName(), sourceModule.getScriptProject());
if (referencedSourceModule == null)
return null;
LuaSourceRoot luaSourceRoot = LuaASTModelUtils.getLuaSourceRoot(referencedSourceModule);
LuaFileAPI fileapi = luaSourceRoot.getFileapi();
if (fileapi != null) {
ArrayList<Return> returns = fileapi.getReturns();
if (returns.size() > 0) {
Return returnValues = returns.get(0);
if (returnValues.getTypes().size() > moduleTypeRef.getReturnPosition() - 1) {
TypeRef typeRef = returnValues.getTypes().get(moduleTypeRef.getReturnPosition() - 1);
return resolveType(referencedSourceModule, typeRef);
}
}
}
return null;
}
public static TypeResolution resolveType(ISourceModule sourceModule, ExprTypeRef exprTypeRef) {
LuaExpression expression = exprTypeRef.getExpression();
if (expression == null)
return null;
return resolveType(sourceModule, expression, exprTypeRef.getReturnPosition());
}
public static TypeResolution resolveType(ISourceModule sourceModule, LuaExpression expr) {
return resolveType(sourceModule, expr, 1);
}
public static TypeResolution getDefaultIndexType(ISourceModule sourceModule, RecordTypeDef recordTypeDef) {
return getDefaultIndexType(new TypeResolution(sourceModule, recordTypeDef), new HashSet<TypeResolution>());
}
public static TypeResolution getDefaultIndexType(TypeResolution recordTypeResolution) {
return getDefaultIndexType(recordTypeResolution, new HashSet<TypeResolution>());
}
private static TypeResolution getDefaultIndexType(TypeResolution recordTypeResolution, Set<TypeResolution> cache) {
if (recordTypeResolution != null && recordTypeResolution.getTypeDef() instanceof RecordTypeDef) {
// search the default index
RecordTypeDef recordTypeDef = (RecordTypeDef) recordTypeResolution.getTypeDef();
TypeRef defaultIndex = recordTypeDef.getDefaultvaluetyperef();
if (defaultIndex != null)
return resolveType(recordTypeResolution.getModule(), defaultIndex);
// if not found we search in hierarchy
// manage super-type fields
// cache is used to avoid cycle
cache.add(recordTypeResolution);
TypeRef supertype = recordTypeDef.getSupertype();
if (supertype != null) {
TypeResolution superTypeResolution = LuaASTUtils.resolveType(recordTypeResolution.getModule(), supertype);
if (!cache.contains(superTypeResolution)) {
return getDefaultIndexType(superTypeResolution, cache);
}
}
}
return null;
}
public static TypeResolution resolveType(ISourceModule sourceModule, LuaExpression expr, int returnposition) {
if (expr instanceof Identifier) {
Definition definition = getDefinition(sourceModule, expr);
// resolve the type of the definition
if (definition == null || definition.getItem() == null || definition.getItem().getType() == null)
return null;
return resolveType(definition.getModule(), definition.getItem().getType());
} else if (expr instanceof Index) {
Definition definition = getDefinition(sourceModule, expr);
if (definition != null && definition.getItem() != null && definition.getItem().getType() != null) {
// resolve the type of the definition
return resolveType(definition.getModule(), definition.getItem().getType());
}
// if not found we search the defaultindex
TypeResolution resolveType = resolveType(sourceModule, ((Index) expr).getLeft());
return getDefaultIndexType(resolveType);
} else if (expr instanceof Call) {
Call call = ((Call) expr);
// resolve the function which is called
TypeResolution resolvedType = resolveType(sourceModule, call.getFunction());
if (resolvedType != null) {
// we must found a function type.
FunctionTypeDef functiontype = null;
if (resolvedType.getTypeDef() instanceof FunctionTypeDef) {
// if the resolved type is function, we get it.
functiontype = (FunctionTypeDef) resolvedType.getTypeDef();
} else if (resolvedType.getTypeDef() instanceof RecordTypeDef) {
// if the resolved type is a record(a table) we get it if it is "callable"
TypeResolution type = resolveType(resolvedType.getModule(), ((RecordTypeDef) resolvedType.getTypeDef()).getCallTypeRef());
if (type != null && type.getTypeDef() instanceof FunctionTypeDef) {
functiontype = (FunctionTypeDef) type.getTypeDef();
}
}
if (functiontype != null && functiontype.getReturns().size() > 0) {
List<TypeRef> types = functiontype.getReturns().get(0).getTypes();
if (types.size() >= returnposition) {
return resolveType(resolvedType.getModule(), types.get(returnposition - 1));
}
}
}
return null;
} else if (expr instanceof Invoke) {
Definition definition = getDefinition(sourceModule, expr);
if (definition == null || definition.getItem() == null || definition.getItem().getType() == null)
return null;
TypeResolution resolvedFunctionType = resolveType(definition.getModule(), definition.getItem().getType());
if (resolvedFunctionType != null && resolvedFunctionType.getTypeDef() instanceof FunctionTypeDef) {
FunctionTypeDef functiontype = (FunctionTypeDef) resolvedFunctionType.getTypeDef();
if (functiontype.getReturns().size() > 0) {
List<TypeRef> types = functiontype.getReturns().get(0).getTypes();
if (types.size() >= returnposition) {
return resolveType(resolvedFunctionType.getModule(), types.get(returnposition - 1));
}
}
}
}
return null;
}
public static TypeResolution resolveType(ISourceModule sourceModule, InlineTypeRef inlineTypeRef) {
TypeDef typeDef = inlineTypeRef.getDefinition();
return new TypeResolution(sourceModule, typeDef);
}
public static class TypeResolution {
private ISourceModule module;
private TypeDef typeDef;
public TypeResolution(ISourceModule module, TypeDef typeDef) {
super();
this.module = module;
this.typeDef = typeDef;
}
public ISourceModule getModule() {
return module;
}
public TypeDef getTypeDef() {
return typeDef;
}
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (this.getClass() != obj.getClass())
return false;
// check content
TypeResolution typeResolution = (TypeResolution) obj;
boolean moduleEquality;
if (this.module == null && typeResolution.module == null)
moduleEquality = true;
else if (this.module != null && this.module.equals(typeResolution.module))
moduleEquality = true;
else
return false;
boolean typeDefEquality;
if (this.typeDef == null && typeResolution.typeDef == null)
typeDefEquality = true;
else if (this.typeDef != null && this.typeDef.equals(typeResolution.typeDef))
typeDefEquality = true;
else
return false;
return typeDefEquality && moduleEquality;
}
@Override
public int hashCode() {
int hash = 1;
hash = 17 * hash + (null == module ? 0 : module.hashCode());
hash = 31 * hash + (null == typeDef ? 0 : typeDef.hashCode());
return hash;
}
}
public static Collection<Item> getLocalVars(LuaSourceRoot luaSourceRoot, final int offset, final String start) {
// the localVars collected, indexed by var name;
final Map<String, Item> collectedLocalVars = new HashMap<String, Item>();
// the visitor which will collect local vars and store it in the map.
ASTVisitor localvarCollector = new ASTVisitor() {
@Override
public boolean visit(ASTNode node) throws Exception {
// we go down util we found the closer block.
if (node instanceof Block) {
if (node.sourceStart() <= offset && offset <= node.sourceEnd()) {
return true;
}
return false;
}
return false;
}
@Override
public boolean endvisit(ASTNode node) throws Exception {
if (node instanceof Block) {
// we go up only on all the parent block which
List<LocalVar> localVars = ((Block) node).getLocalVars();
for (LocalVar localVar : localVars) {
Item item = localVar.getVar();
if (!collectedLocalVars.containsKey(item.getName())
&& (start == null || item.getName().toLowerCase().startsWith(start.toLowerCase()))) {
collectedLocalVars.put(item.getName(), item);
}
}
return true;
}
return false;
}
};
// traverse the root block on the file with this visitor
try {
luaSourceRoot.getInternalContent().getContent().traverse(localvarCollector);
// CHECKSTYLE:OFF
} catch (Exception e) {
// CHECKSTYLE:ON
Activator.logError("unable to collect local var", e); //$NON-NLS-1$
}
return collectedLocalVars.values();
}
public static LuaExpression getLuaExpressionAt(LuaSourceRoot luaSourceRoot, final int startOffset, final int endOffset) {
// traverse the root block on the file with this visitor
try {
MatchNodeVisitor matchNodeVisitor = new MatchNodeVisitor(startOffset, endOffset, LuaExpression.class);
luaSourceRoot.getInternalContent().getContent().traverse(matchNodeVisitor);
return (LuaExpression) matchNodeVisitor.getNode();
// CHECKSTYLE:OFF
} catch (Exception e) {
// CHECKSTYLE:ON
Activator.logError("unable to get expression at", e); //$NON-NLS-1$
}
return null;
}
public static class Definition {
private ISourceModule module;
private Item item;
public Definition(ISourceModule module, Item item) {
super();
this.module = module;
this.item = item;
}
public ISourceModule getModule() {
return module;
}
public Item getItem() {
return item;
}
}
public static Definition getDefinition(ISourceModule sourceModule, RecordTypeDef recordTypeDef, String fieldname) {
return getDefinition(new TypeResolution(sourceModule, recordTypeDef), fieldname, new HashSet<TypeResolution>());
}
private static Definition getDefinition(TypeResolution recordTypeResolution, String fieldname, Set<TypeResolution> cache) {
if (recordTypeResolution != null && recordTypeResolution.getTypeDef() instanceof RecordTypeDef) {
// search field with the given field name
RecordTypeDef recordtypedef = (RecordTypeDef) recordTypeResolution.getTypeDef();
Item item = recordtypedef.getFields().get(fieldname);
if (item != null)
return new Definition(recordTypeResolution.getModule(), item);
// if not found we search in hierarchy
// manage super-type fields
// cache is used to avoid cycle
cache.add(recordTypeResolution);
TypeRef supertype = recordtypedef.getSupertype();
if (supertype != null) {
TypeResolution superTypeResolution = LuaASTUtils.resolveType(recordTypeResolution.getModule(), supertype);
if (!cache.contains(superTypeResolution)) {
return getDefinition(superTypeResolution, fieldname, cache);
}
}
}
return null;
}
public static Definition getDefinition(ISourceModule sourceModule, LuaExpression luaExpression) {
if (luaExpression instanceof Identifier) {
Identifier identifier = (Identifier) luaExpression;
if (identifier.getDefinition() != null) {
Item definition = identifier.getDefinition();
if (definition instanceof UnknownItem) {
// if we don't know the definition try to guess it
final String identifiername = definition.getName();
final LuaSourceRoot luaSourceRoot = LuaASTModelUtils.getLuaSourceRoot(sourceModule);
// search local variable at first
Item localvarItem = LuaASTUtils.getClosestLocalVar(luaSourceRoot, identifiername, identifier.start());
if (localvarItem != null) {
return new Definition(sourceModule, localvarItem);
}
// if not found, try to find global
Definition globalVarDefinition = LuaASTUtils.getGlobalVarDefinition(sourceModule, identifiername);
if (globalVarDefinition != null)
return globalVarDefinition;
return null;
}
if (LuaASTUtils.isUnresolvedGlobal(definition)) {
// in this case we have a unknown global var definition.
// we will try to resolved it
Definition globalVarDefinition = getGlobalVarDefinition(sourceModule, definition.getName());
if (globalVarDefinition != null)
return globalVarDefinition;
}
return new Definition(sourceModule, definition);
}
} else if (luaExpression instanceof Index) {
Index index = (Index) luaExpression;
TypeResolution resolveType = LuaASTUtils.resolveType(sourceModule, index.getLeft());
if (resolveType != null && resolveType.getTypeDef() instanceof RecordTypeDef) {
RecordTypeDef typeDef = (RecordTypeDef) resolveType.getTypeDef();
return getDefinition(resolveType.getModule(), typeDef, index.getRight());
}
} else if (luaExpression instanceof Invoke) {
Invoke invoke = (Invoke) luaExpression;
TypeResolution resolveType = LuaASTUtils.resolveType(sourceModule, invoke.getRecord());
if (resolveType != null && resolveType.getTypeDef() instanceof RecordTypeDef) {
RecordTypeDef typeDef = (RecordTypeDef) resolveType.getTypeDef();
return getDefinition(resolveType.getModule(), typeDef, invoke.getFunctionName());
}
} else if (luaExpression instanceof Call) {
Call call = (Call) luaExpression;
Definition definition = getDefinition(sourceModule, call.getFunction());
return definition;
}
return null;
}
public static List<Definition> getAllGlobalVarsDefinition(final ISourceModule sourceModule, final String start) {
final List<Definition> definitions = new ArrayList<Definition>();
// SEARCH IN PRELOADED SOURCE MODULE
ISourceModule preloadedSourceModule = getPreloadSourceModule(sourceModule);
if (preloadedSourceModule != null) {
definitions.addAll(getAllInternalGlobalVarsDefinition(preloadedSourceModule, start));
}
if (Platform.getPreferencesService().getBoolean(LuaLanguageToolkit.getDefault().getPreferenceQualifier(),
PreferenceInitializer.USE_GLOBAL_VAR_IN_LDT, true, null)) {
// SEARCH IN CURRENT SOURCE MODULE
definitions.addAll(getAllInternalGlobalVarsDefinition(sourceModule, start));
// SEARCH IN EXTERNAL SOURCE MODULE
definitions.addAll(getAllExternalGlobalVarsDefinition(sourceModule, start));
}
return definitions;
}
public static List<Definition> getAllInternalGlobalVarsDefinition(final ISourceModule sourceModule, final String start) {
final List<Definition> definitions = new ArrayList<Definition>();
// global vars defined in current module.
LuaSourceRoot currentluaSourceRoot = LuaASTModelUtils.getLuaSourceRoot(sourceModule);
if (currentluaSourceRoot != null) {
// global var which start with 'start'
for (Item globalvar : currentluaSourceRoot.getFileapi().getGlobalvars().values()) {
if (start == null || start.isEmpty() || globalvar.getName().toLowerCase().startsWith(start.toLowerCase()))
definitions.add(new Definition(sourceModule, globalvar));
}
}
return definitions;
}
public static List<Definition> getAllExternalGlobalVarsDefinition(final ISourceModule originalSourceModule, final String start) {
return getExternalGlobalVarsDefinition(originalSourceModule, start, false);
}
private static List<Definition> getExternalGlobalVarsDefinition(final ISourceModule originalSourceModule, final String start,
final boolean exactName) {
final List<Definition> definitions = new ArrayList<Definition>();
IProjectSourceVisitor2 visitor = new IProjectSourceVisitor2() {
@Override
public void processFile(ISourceModule sourceModule, IPath absolutePath, IPath relativePath, String charset, IProgressMonitor monitor)
throws CoreException {
if (sourceModule != null && !sourceModule.equals(originalSourceModule)) {
if (exactName) {
Definition globalVarDef = getInternalGlobalVarDefinition(sourceModule, start);
if (globalVarDef != null)
definitions.add(globalVarDef);
} else {
definitions.addAll(getAllInternalGlobalVarsDefinition(sourceModule, start));
}
}
}
@Override
public void processDirectory(IScriptFolder sourceModule, IPath absolutePath, IPath relativePath, IProgressMonitor monitor)
throws CoreException {
// nothing to do
}
};
try {
LuaUtils.visitSourceFiles(originalSourceModule.getScriptProject(), EnumSet.of(ProjectFragmentFilter.DEPENDENT_PROJECT), visitor,
new NullProgressMonitor());
} catch (CoreException e) {
Activator.logError("Unable to get external global for auto-complete", e); //$NON-NLS-1$
}
return definitions;
}
public static Definition getGlobalVarDefinition(ISourceModule sourceModule, String varname) {
// SEARCH IN PRELOADED SOURCE MODULE
Definition definition = getGlobalVarDefinitionInPreloadedSourceModule(sourceModule, varname);
if (definition != null)
return definition;
if (Platform.getPreferencesService().getBoolean(LuaLanguageToolkit.getDefault().getPreferenceQualifier(),
PreferenceInitializer.USE_GLOBAL_VAR_IN_LDT, true, null)) {
// SEARCH IN CURRENT SOURCE MODULE
definition = getInternalGlobalVarDefinition(sourceModule, varname);
if (definition != null)
return definition;
// SEARCH IN EXTERNAL SOURCE MODULE
definition = getExternalGlobalVarDefinition(sourceModule, varname);
if (definition != null)
return definition;
}
return null;
}
public static Definition getGlobalVarDefinitionInPreloadedSourceModule(ISourceModule sourceModule, String varname) {
// get preloaded module
ISourceModule preloadedSourceModule = getPreloadSourceModule(sourceModule);
if (preloadedSourceModule == null)
return null;
// get luasourceroot
LuaSourceRoot preloadedLuaSourceRoot = LuaASTModelUtils.getLuaSourceRoot(preloadedSourceModule);
if (preloadedLuaSourceRoot == null)
return null;
// get a global var with this name
Item item = preloadedLuaSourceRoot.getFileapi().getGlobalvars().get(varname);
if (item == null)
return null;
return new Definition(preloadedSourceModule, item);
}
public static Definition getInternalGlobalVarDefinition(ISourceModule sourceModule, String varname) {
// get luasourceroot
LuaSourceRoot luaSourceRoot = LuaASTModelUtils.getLuaSourceRoot(sourceModule);
if (luaSourceRoot == null)
return null;
// get a global var with this name
Item item = luaSourceRoot.getFileapi().getGlobalvars().get(varname);
if (item == null)
return null;
return new Definition(sourceModule, item);
}
public static Definition getExternalGlobalVarDefinition(final ISourceModule originalSourceModule, final String start) {
List<Definition> definitions = getExternalGlobalVarsDefinition(originalSourceModule, start, true);
if (!definitions.isEmpty()) {
return definitions.get(0);
}
return null;
}
public static ISourceModule getPreloadSourceModule(ISourceModule sourceModule) {
if (sourceModule != null && sourceModule.getScriptProject() != null) {
return LuaUtils.getSourceModule("global", sourceModule.getScriptProject()); //$NON-NLS-1$
}
return null;
}
public static boolean isModule(LuaFileAPI luaFileAPI, RecordTypeDef recordTypeDef) {
TypeRef moduleReturnTypeRef = getModuleReturnType(luaFileAPI);
if (!(moduleReturnTypeRef instanceof InternalTypeRef))
return false;
String typename = ((InternalTypeRef) moduleReturnTypeRef).getTypeName();
return luaFileAPI.getTypes().get(typename) == recordTypeDef;
}
public static boolean isInlineTypeDef(TypeDef typedef) {
return typedef != null && typedef.getParent() instanceof Item;
}
public static boolean isInlineTypeField(Item item) {
return item.getParent() instanceof RecordTypeDef && isInlineTypeDef((TypeDef) item.getParent());
}
public static boolean isLocalVariable(Item item) {
return item.getParent() instanceof Block;
}
public static boolean isGlobalVariable(Item item) {
return item.getParent() instanceof LuaFileAPI;
}
public static boolean isUnresolvedGlobal(Item item) {
return item.getParent() instanceof LuaInternalContent;
}
public static boolean isTypeField(Item item) {
return item.getParent() instanceof RecordTypeDef;
}
public static boolean isModuleTypeField(LuaFileAPI luaFileAPI, Item item) {
LuaASTNode parent = item.getParent();
if (parent instanceof RecordTypeDef) {
return isModule(luaFileAPI, (RecordTypeDef) parent);
}
return false;
}
// return true is the element is part of a module declaration
// a module declaration is considered as public too
public static boolean isModule(LuaFileAPI luaFileAPI, LuaASTNode node) {
if (node instanceof Item) {
Item item = (Item) node;
if (isInlineTypeField(item)) {
// should be always true as item is from inline Type
if (item.getParent() instanceof RecordTypeDef) {
LuaASTNode parent = ((RecordTypeDef) item.getParent()).getParent();
return isModule(luaFileAPI, parent);
}
}
return isModuleTypeField(luaFileAPI, item);
} else if (node instanceof TypeDef) {
TypeDef typedef = (TypeDef) node;
if (isInlineTypeDef(typedef)) {
return isModule(luaFileAPI, ((TypeDef) node).getParent());
}
}
return false;
}
// return true if the element is part of a public declaration (global var or type declaration)
// a module declaration is considered as public too
public static boolean isPublic(LuaASTNode node) {
if (node instanceof Item) {
Item item = (Item) node;
if (isInlineTypeField(item)) {
// should be always true as item is from inline Type
if (item.getParent() instanceof RecordTypeDef) {
LuaASTNode parent = ((RecordTypeDef) item.getParent()).getParent();
return isPublic(parent);
}
}
return isGlobalVariable(item) || isTypeField(item);
} else if (node instanceof TypeDef) {
TypeDef typedef = (TypeDef) node;
if (isInlineTypeDef(typedef)) {
return isPublic(((TypeDef) node).getParent());
}
}
return false;
}
// return true if the element is part of a private declaration (local variable)
public static boolean isPrivate(LuaASTNode node) {
if (node instanceof Item) {
Item item = (Item) node;
if (isInlineTypeField(item)) {
// should be always true as item is from inline Type
if (item.getParent() instanceof RecordTypeDef) {
LuaASTNode parent = ((RecordTypeDef) item.getParent()).getParent();
return isPrivate(parent);
}
}
return isLocalVariable(item);
} else if (node instanceof TypeDef) {
TypeDef typedef = (TypeDef) node;
if (isInlineTypeDef(typedef)) {
return isPrivate(((TypeDef) node).getParent());
}
}
return false;
}
public static TypeDef resolveTypeLocaly(ISourceModule sourceModule, Item item) {
LuaSourceRoot luaSourceRoot = LuaASTModelUtils.getLuaSourceRoot(sourceModule);
if (luaSourceRoot != null)
return resolveTypeLocaly(luaSourceRoot.getFileapi(), item);
return null;
}
public static TypeDef resolveTypeLocaly(LuaFileAPI luaFileAPI, Item item) {
if (item == null)
return null;
TypeRef typeref = item.getType();
if (typeref instanceof InternalTypeRef) {
if (luaFileAPI == null)
return null;
InternalTypeRef internaltyperef = (InternalTypeRef) typeref;
TypeDef typeDef = luaFileAPI.getTypes().get(internaltyperef.getTypeName());
return typeDef;
} else if (typeref instanceof InlineTypeRef) {
InlineTypeRef inlinetyperef = (InlineTypeRef) typeref;
TypeDef typeDef = inlinetyperef.getDefinition();
return typeDef;
}
return null;
}
public static TypeRef getModuleReturnType(LuaFileAPI luaFileAPI) {
ArrayList<Return> returns = luaFileAPI.getReturns();
if (returns.isEmpty())
return null;
Return returnValues = returns.get(0);
if (returnValues.getTypes().isEmpty())
return null;
return returnValues.getTypes().get(0);
}
}