All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.xtext.java.resource.IndexAwareNameEnvironment Maven / Gradle / Ivy

/**
 * Copyright (c) 2018, 2020 itemis AG (http://www.itemis.eu) and others.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.eclipse.xtext.java.resource;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
import org.eclipse.xtext.common.types.TypesPackage;
import org.eclipse.xtext.common.types.descriptions.EObjectDescriptionBasedStubGenerator;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.resource.IResourceDescription;
import org.eclipse.xtext.resource.IResourceDescriptions;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.IterableExtensions;

public class IndexAwareNameEnvironment implements INameEnvironment {
	private final Resource resource;

	private final ClassLoader classLoader;

	private final IResourceDescriptions resourceDescriptions;

	private final EObjectDescriptionBasedStubGenerator stubGenerator;

	private final ClassFileCache classFileCache;

	private Map nameToAnswerCache = new HashMap<>();

	@Override
	public void cleanup() {
		nameToAnswerCache.clear();
		classFileCache.clear();
	}

	@Override
	public NameEnvironmentAnswer findType(char[][] compoundTypeName) {
		List segments = Arrays.stream(compoundTypeName).map(String::valueOf).collect(Collectors.toList());
		QualifiedName className = QualifiedName.create(segments);
		return findType(className);
	}

	public NameEnvironmentAnswer findType(QualifiedName className) {
		try {
			if (classFileCache.containsKey(className)) {
				IBinaryType t = classFileCache.get(className);
				if (t == null) {
					return null;
				}
				return new NameEnvironmentAnswer(t, null);
			}
			if (nameToAnswerCache.containsKey(className)) {
				return nameToAnswerCache.get(className);
			}
			IEObjectDescription candidate = IterableExtensions.head(
					resourceDescriptions.getExportedObjects(TypesPackage.Literals.JVM_DECLARED_TYPE, className, false));
			NameEnvironmentAnswer result = null;
			if (candidate != null) {
				IResourceDescription resourceDescription = resourceDescriptions
						.getResourceDescription(candidate.getEObjectURI().trimFragment());
				Resource res = resource.getResourceSet().getResource(resourceDescription.getURI(), false);
				String source = null;
				if (res instanceof JavaResource) {
					source = ((JavaResource) res).getOriginalSource();
				} else {
					source = stubGenerator.getJavaStubSource(candidate, resourceDescription);
				}
				CompilationUnit compilationUnit = new CompilationUnit(source.toCharArray(),
						className.toString("/") + ".java", null);
				result = new NameEnvironmentAnswer(compilationUnit, null);
			} else {
				String fileName = className.toString("/") + ".class";
				URL url = classLoader.getResource(fileName);
				if (url == null) {
					nameToAnswerCache.put(className, null);
					classFileCache.put(className, null);
					return null;
				}
				IBinaryType reader = null;
				try (InputStream stream = url.openStream()) {
					reader = ClassFileReader.read(stream, fileName);
				}
				if (reader == null) {
					return null;
				}
				classFileCache.put(className, reader);
				result = new NameEnvironmentAnswer(reader, null);
			}
			nameToAnswerCache.put(className, result);
			return result;
		} catch (IOException | ClassFormatException e) {
			throw Exceptions.sneakyThrow(e);
		}
	}

	@Override
	public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
		List segments = Arrays.stream(packageName).map(String::valueOf).collect(Collectors.toList());
		segments.add(String.valueOf(typeName));
		QualifiedName className = QualifiedName.create(segments);
		return findType(className);
	}

	@Override
	public boolean isPackage(char[][] parentPackageName, char[] packageName) {
		if (packageName == null || packageName.length == 0) {
			return false;
		}
		return Character.isLowerCase(packageName[0]);
	}

	public IndexAwareNameEnvironment(Resource resource, ClassLoader classLoader,
			IResourceDescriptions resourceDescriptions, EObjectDescriptionBasedStubGenerator stubGenerator,
			ClassFileCache classFileCache) {
		this.resource = resource;
		this.classLoader = classLoader;
		this.resourceDescriptions = resourceDescriptions;
		this.stubGenerator = stubGenerator;
		this.classFileCache = classFileCache;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy