Package org.erlide.engine.internal.model.erlang

Source Code of org.erlide.engine.internal.model.erlang.ModelInternalUtils

/*******************************************************************************
* Copyright (c) 2009-2013 Vlad Dumitrescu 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:
*     Vlad Dumitrescu
*******************************************************************************/
package org.erlide.engine.internal.model.erlang;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.erlide.engine.ErlangEngine;
import org.erlide.engine.model.ErlModelException;
import org.erlide.engine.model.IErlModel;
import org.erlide.engine.model.erlang.ErlangFunction;
import org.erlide.engine.model.erlang.IErlImport;
import org.erlide.engine.model.erlang.IErlModule;
import org.erlide.engine.model.erlang.IErlPreprocessorDef;
import org.erlide.engine.model.root.ErlElementKind;
import org.erlide.engine.model.root.IErlElement;
import org.erlide.engine.model.root.IErlExternal;
import org.erlide.engine.model.root.IErlProject;
import org.erlide.engine.services.search.ModelUtilService;
import org.erlide.runtime.api.IOtpRpc;
import org.erlide.util.ErlLogger;
import org.erlide.util.erlang.TypeConverter;

import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangList;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangTuple;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

public class ModelInternalUtils implements ModelUtilService {

    private final IOtpRpc backend;

    public ModelInternalUtils(final IOtpRpc backend) {
        this.backend = backend;
    }

    private static final String DELIMITER = "<>";

    @Override
    public String getExternalModulePath(final IErlModule module) {
        final List<String> result = Lists.newArrayList();
        IErlElement element = module;
        while (element != null) {
            if (element instanceof IErlExternal) {
                final IErlExternal external = (IErlExternal) element;
                result.add(external.getName());
            } else {
                result.add(element.getName());
            }
            element = element.getParent();
        }
        return Joiner.on(DELIMITER).join(Lists.reverse(result));
    }

    private IErlExternal getElementWithExternalName(final IErlElement parent,
            final String segment) throws ErlModelException {
        for (final IErlElement i : parent.getChildrenOfKind(ErlElementKind.EXTERNAL_ROOT,
                ErlElementKind.EXTERNAL_APP, ErlElementKind.EXTERNAL_FOLDER)) {
            final IErlExternal external = (IErlExternal) i;
            final String externalName = external.getName();
            if (externalName.equals(segment)) {
                return external;
            }
        }
        return null;
    }

    @Override
    public IErlModule getModuleFromExternalModulePath(final IErlModel model,
            final String modulePath) throws ErlModelException {
        final List<String> path = Lists.newArrayList(Splitter.on(DELIMITER).split(
                modulePath));
        model.open(null);
        final IErlElement childNamed = model.getChildNamed(path.get(0));
        if (childNamed != null) {
            IErlElement parent = childNamed;
            final int n = path.size() - 1;
            for (int i = 1;; i++) {
                if (parent == null) {
                    break;
                }
                final IErlElement ErlElement = parent;
                ErlElement.open(null);
                if (i == n) {
                    break;
                }
                parent = getElementWithExternalName(parent, path.get(i));
            }
            if (parent != null) {
                final IErlElement child = parent.getChildNamed(path.get(n));
                if (child instanceof IErlModule) {
                    return (IErlModule) child;
                }
            }
        }
        return null;
    }

    @Override
    public List<String> findUnitsWithPrefix(final String prefix,
            final IErlProject project, final boolean checkExternals,
            final boolean includes) throws ErlModelException {
        final List<String> result = Lists.newArrayList();
        final Collection<IErlModule> units = getUnits(project, checkExternals, includes);
        addUnitNamesWithPrefix(prefix, result, units, false, includes);
        if (project != null) {
            for (final IErlProject p : project.getReferencedProjects()) {
                if (p != null) {
                    p.open(null);
                    addUnitNamesWithPrefix(prefix, result,
                            getUnits(p, checkExternals, includes), false, includes);
                }
            }
            if (checkExternals) {
                final Collection<IErlModule> externalUnits = includes ? project
                        .getExternalIncludes() : project.getExternalModules();
                addUnitNamesWithPrefix(prefix, result, externalUnits, true, includes);
            }
        }
        return result;
    }

    private Collection<IErlModule> getUnits(final IErlProject project,
            final boolean checkExternals, final boolean includes)
            throws ErlModelException {
        final Collection<IErlModule> units;
        if (!includes && project != null) {
            units = project.getModules();
        } else if (!checkExternals && project != null) {
            units = project.getIncludes();
        } else {
            units = Sets.newHashSet();
        }
        return units;
    }

    @Override
    public List<OtpErlangObject> getImportsAsList(final IErlModule mod) {
        if (mod == null) {
            return NO_IMPORTS;
        }
        final Collection<IErlImport> imports = mod.getImports();
        if (imports.isEmpty()) {
            return NO_IMPORTS;
        }
        final List<OtpErlangObject> result = new ArrayList<OtpErlangObject>(
                imports.size());
        for (final IErlImport i : imports) {
            final Collection<ErlangFunction> functions = i.getFunctions();
            final OtpErlangObject funsT[] = new OtpErlangObject[functions.size()];
            int j = 0;
            for (final ErlangFunction f : functions) {
                funsT[j] = f.getNameArityTuple();
                j++;
            }
            final OtpErlangTuple modFunsT = new OtpErlangTuple(new OtpErlangObject[] {
                    new OtpErlangAtom(i.getImportModule()), new OtpErlangList(funsT) });
            result.add(modFunsT);
        }
        return result;
    }

    @Override
    public List<IErlPreprocessorDef> getAllPreprocessorDefs(final IErlModule module,
            final ErlElementKind kind) throws CoreException {
        final List<IErlPreprocessorDef> result = Lists.newArrayList();
        final List<IErlModule> modulesWithIncludes = Lists.newArrayList(ErlangEngine
                .getInstance().getModelFindService().findAllIncludedFiles(module));
        modulesWithIncludes.add(module);
        for (final IErlModule m : modulesWithIncludes) {
            result.addAll(m.getPreprocessorDefs(kind));
        }
        return result;
    }

    public static final List<OtpErlangObject> NO_IMPORTS = new ArrayList<OtpErlangObject>(
            0);

    private void addUnitNamesWithPrefix(final String prefix, final List<String> result,
            final Collection<IErlModule> modules, final boolean external,
            final boolean includes) {
        for (final IErlModule module : modules) {
            String moduleName = includes ? module.getName() : module.getModuleName();
            if (external && includes) {
                moduleName = getIncludeLibPath(module);
            }
            boolean nameMatches = moduleName.startsWith(prefix);
            if (!nameMatches && prefix.startsWith("'")) {
                nameMatches = moduleName.startsWith(prefix.substring(1));
            }
            if (nameMatches && (includes || !module.getName().endsWith(".hrl"))) {
                if (!result.contains(moduleName)) {
                    final String name = new OtpErlangAtom(moduleName).toString();
                    result.add(name);
                }
            }
        }
    }

    private String getIncludeLibPath(final IErlModule module) {
        String s = module.getName();
        String prevS = s;
        IErlElement e = module;
        for (;;) {
            final IErlElement p = e.getParent();
            if (p instanceof IErlProject) {
                break;
            }
            e = p;
            prevS = s;
            s = e.getName() + "/" + s;
        }
        return prevS;
    }

    @Override
    public String[] getPredefinedMacroNames() {
        return new String[] { "MODULE", "LINE", "FILE" };
    }

    @Override
    public boolean isOtpModule(final IErlModule module) {
        IErlElement parent = module.getParent();
        while (parent instanceof IErlExternal) {
            final IErlExternal external = (IErlExternal) parent;
            if (external.isOTP()) {
                return true;
            }
            parent = external.getParent();
        }
        return false;
    }

    @Override
    public IErlModule getModule(final IErlElement element) {
        if (element instanceof IErlModule) {
            return (IErlModule) element;
        }
        return (IErlModule) element.getAncestorOfKind(ErlElementKind.MODULE);
    }

    @Override
    public IErlProject getProject(final IErlElement element) {
        if (element == null) {
            return null;
        }
        final IErlElement ancestor = element.getAncestorOfKind(ErlElementKind.PROJECT);
        if (ancestor instanceof IErlProject) {
            return (IErlProject) ancestor;
        }
        return null;
    }

    /**
     * Helper method - returns the targeted item (IResource if internal or
     * java.io.File if external), or null if unbound Internal items must be
     * referred to using container relative paths.
     */
    @Override
    public Object getTarget(final IContainer container, final IPath path,
            final boolean checkResourceExistence) {

        if (path == null) {
            return null;
        }

        // lookup - inside the container
        if (path.getDevice() == null) { // container relative paths should not
            // contain a device
            // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684)
            // (case of a workspace rooted at d:\ )
            final IResource resource = container.findMember(path);
            if (resource != null) {
                if (!checkResourceExistence || resource.exists()) {
                    return resource;
                }
                return null;
            }
        }

        // if path is relative, it cannot be an external path
        // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
        if (!path.isAbsolute()) {
            return null;
        }

        // lookup - outside the container
        final File externalFile = new File(path.toOSString());
        if (!checkResourceExistence) {
            return externalFile;
        }
        if (externalFile.exists()) {
            return externalFile;
        }
        return null;
    }

    @Override
    public String getModuleInfo(final IErlModule module) {
        final String errorValue = "There is no module information about this file.";
        if (module == null) {
            return errorValue;
        }

        final IErlProject project = getProject(module);
        final IPath beamPath = project.getProperties().getOutputDir()
                .append(module.getModuleName()).addFileExtension("beam");
        final IFile beam = project.getWorkspaceProject().getFile(beamPath);

        try {
            final OtpErlangObject info = backend.call("erlide_backend",
                    "get_module_info", "s", beam.getLocation().toPortableString());
            return (String) TypeConverter.erlang2java(info, String.class);
        } catch (final Exception e) {
            ErlLogger.warn(e);
        }
        return errorValue;
    }
}
TOP

Related Classes of org.erlide.engine.internal.model.erlang.ModelInternalUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.