package org.erlide.engine.internal.model.erlang; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.erlide.engine.ErlangEngine; import org.erlide.engine.internal.model.SourceRange; import org.erlide.engine.model.ErlElementKind; import org.erlide.engine.model.ErlModelException; import org.erlide.engine.model.IErlElement; import org.erlide.engine.model.erlang.ErlangFunction; import org.erlide.engine.model.erlang.IErlFunction; import org.erlide.engine.model.erlang.IErlPreprocessorDef; import org.erlide.engine.model.erlang.IErlTypespec; import org.erlide.engine.model.erlang.ISourceRange; import org.erlide.engine.model.root.IErlElementLocator; import org.erlide.engine.model.root.IErlModule; import org.erlide.engine.model.root.IErlProject; import org.erlide.engine.services.search.ModelFindService; import org.erlide.engine.services.search.OpenService; import org.erlide.runtime.rpc.IOtpRpc; import org.erlide.util.StringUtils; import com.ericsson.otp.erlang.OtpErlangLong; import com.ericsson.otp.erlang.OtpErlangRangeException; import com.ericsson.otp.erlang.OtpErlangTuple; import com.google.common.collect.Lists; public class ModelFindUtil implements ModelFindService { public ModelFindUtil(final IOtpRpc backend) { } @Override public ISourceRange findVariable(final ISourceRange range, final String variableName, final String elementText) throws OtpErlangRangeException { final OtpErlangTuple res2 = ErlangEngine.getInstance() .getService(OpenService.class).findFirstVar(variableName, elementText); if (res2 != null) { final int relativePos = ((OtpErlangLong) res2.elementAt(0)).intValue() - 1; final int length = ((OtpErlangLong) res2.elementAt(1)).intValue(); final int start = relativePos + range.getOffset(); return new SourceRange(start, length); } return range; } @Override public IErlModule findInclude(final IErlElementLocator model, final IErlProject project, final IErlModule module, final String includeName, final String includePath) throws CoreException { if (module != null) { final IErlModule include = model.findIncludeFromModule(module, includeName, includePath, IErlElementLocator.Scope.REFERENCED_PROJECTS); if (include != null) { return include; } } else if (project != null) { final IErlModule include = model.findIncludeFromProject(project, includeName, includePath, IErlElementLocator.Scope.REFERENCED_PROJECTS); if (include != null) { return include; } } return null; } @Override public IErlTypespec findTypespec(final IErlModule module, final String name) throws CoreException { IErlTypespec typespec = module.findTypespec(name); if (typespec != null) { return typespec; } final Collection<IErlModule> includedFiles = ErlangEngine.getInstance() .getModelSearcherService().findAllIncludedFiles(module); for (final IErlModule includedFile : includedFiles) { typespec = includedFile.findTypespec(name); if (typespec != null) { return typespec; } } return null; } @Override public IErlFunction findFunction(final IErlElementLocator model, final IErlProject project, final IErlModule module, final String moduleName0, final String modulePath, final ErlangFunction erlangFunction, final IErlElementLocator.Scope scope) throws CoreException { if (moduleName0 != null) { final String moduleName = resolveMacroValue(moduleName0, module); final IErlModule module2 = findModule(model, project, moduleName, modulePath, scope); if (module2 != null) { module2.open(null); final IErlFunction function = module2.findFunction(erlangFunction); if (function != null) { return function; } return null; } } return null; } @Override public IErlModule findModule(final IErlElementLocator model, final IErlProject project, final String moduleName, final String modulePath, final IErlElementLocator.Scope scope) throws ErlModelException { if (project != null) { return model.findModuleFromProject(project, moduleName, modulePath, scope); } if (scope == IErlElementLocator.Scope.ALL_PROJECTS) { return model.findModule(moduleName, modulePath); } return null; } @Override public IErlElement findTypeDef(final IErlElementLocator model, final IErlProject project, final IErlModule module, final String moduleName0, final String typeName, final String modulePath, final IErlElementLocator.Scope scope) throws CoreException { final String moduleName = resolveMacroValue(moduleName0, module); final IErlModule module2 = findModule(model, project, moduleName, modulePath, scope); if (module2 != null) { module2.open(null); return module2.findTypespec(typeName); } return null; } @Override public IErlPreprocessorDef findPreprocessorDef(final Collection<IErlProject> projects, final String moduleName, final String definedName, final ErlElementKind kind) throws CoreException { for (final IErlProject project : projects) { if (project != null) { final IErlModule module = project.getModule(moduleName); if (module != null) { final IErlPreprocessorDef def = findPreprocessorDef(module, definedName, kind); if (def != null) { return def; } } } } return null; } @Override public IErlPreprocessorDef findPreprocessorDef(final IErlModule module, final String definedName, final ErlElementKind kind) throws CoreException { String unquoted = StringUtils.unquote(definedName); final String quoted = StringUtils.quote(definedName); final Set<String> names = new HashSet<>(3); if (kind == ErlElementKind.RECORD_DEF) { while (names.add(unquoted)) { unquoted = resolveMacroValue(unquoted, module); } } else { names.add(unquoted); } names.add(quoted); names.add(definedName); final List<IErlModule> allIncludedFiles = Lists.newArrayList(ErlangEngine .getInstance().getModelSearcherService().findAllIncludedFiles(module)); allIncludedFiles.add(0, module); for (final IErlModule includedFile : allIncludedFiles) { for (final String name : names) { includedFile.open(null); final IErlPreprocessorDef preprocessorDef = includedFile .findPreprocessorDef(name, kind); if (preprocessorDef != null) { return preprocessorDef; } } } return null; } @Override public String resolveMacroValue(final String definedName, final IErlModule module) { if (module != null) { if ("?MODULE".equals(definedName)) { return module.getModuleName(); } final IErlPreprocessorDef def = module.findPreprocessorDef( StringUtils.withoutInterrogationMark(definedName), ErlElementKind.MACRO_DEF); if (def != null) { final String extra = def.getExtra(); final int p = extra.indexOf(','); if (p != -1) { final String s = extra.substring(p + 1).trim(); if (s.length() > 0) { return s; } } } } return definedName; } }