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

org.eclipse.jdt.internal.compiler.batch.BasicModule Maven / Gradle / Ivy

There is a newer version: 3.39.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2016 IBM Corporation.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.batch;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Predicate;
import java.util.stream.Stream;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.ExportsStatement;
import org.eclipse.jdt.internal.compiler.ast.ModuleDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ModuleReference;
import org.eclipse.jdt.internal.compiler.ast.OpensStatement;
import org.eclipse.jdt.internal.compiler.ast.RequiresStatement;
import org.eclipse.jdt.internal.compiler.ast.ProvidesStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UsesStatement;
import org.eclipse.jdt.internal.compiler.env.IModule;
import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
import org.eclipse.jdt.internal.compiler.env.ModuleReferenceImpl;
import org.eclipse.jdt.internal.compiler.env.PackageExportImpl;

public class BasicModule implements IModule {
	static class Service implements IModule.IService {
		char[] provides;
		char[][] with;
		@Override
		public char[] name() {
			return this.provides;
		}

		@Override
		public char[][] with() {
			return this.with;
		}
		public String toString() {
			StringBuffer buffer = new StringBuffer();
			buffer.append("provides"); //$NON-NLS-1$
			buffer.append(this.provides);
			buffer.append(" with "); //$NON-NLS-1$
			buffer.append(this.with);
			buffer.append(';');
			return buffer.toString();
		}
	}
	private static PackageExportImpl createPackageExport(ExportsStatement[] refs, int i) {
		ExportsStatement ref = refs[i];
		PackageExportImpl exp = new PackageExportImpl();
		exp.pack = ref.pkgName;
		ModuleReference[] imp = ref.targets;
		if (imp != null) {
			exp.exportedTo = new char[imp.length][];
			for(int j = 0; j < imp.length; j++) {
				exp.exportedTo = imp[j].tokens;
			}
		}
		return exp;
	}
	private static Service createService(TypeReference service, TypeReference[] with) {
		Service ser = new Service();
		ser.provides = CharOperation.concatWith(service.getTypeName(), '.');
		ser.with = new char[with.length][];
		for (int i = 0; i < with.length; i++) {
			ser.with[i] = CharOperation.concatWith(with[i].getTypeName(), '.');
		}
		return ser;
	}
	private static PackageExportImpl createPackageOpen(OpensStatement ref) {
		PackageExportImpl exp = new PackageExportImpl();
		exp.pack = ref.pkgName;
		ModuleReference[] imp = ref.targets;
		if (imp != null) {
			exp.exportedTo = new char[imp.length][];
			for(int j = 0; j < imp.length; j++) {
				exp.exportedTo = imp[j].tokens;
			}
		}
		return exp;
	}

	boolean isAutomodule;
	private boolean isOpen = false;
	char[] name;
	IModule.IModuleReference[] requires;
	IModule.IPackageExport[] exports;
	char[][] uses;
	Service[] provides;
	IModule.IPackageExport[] opens;
	public BasicModule(ModuleDeclaration descriptor, IModulePathEntry root) {
		this.name = descriptor.moduleName;
		if (descriptor.requiresCount > 0) {
			RequiresStatement[] refs = descriptor.requires;
			this.requires = new ModuleReferenceImpl[refs.length];
			for (int i = 0; i < refs.length; i++) {
				ModuleReferenceImpl ref = new ModuleReferenceImpl();
				ref.name = CharOperation.concatWith(refs[i].module.tokens, '.');
				ref.modifiers = refs[i].modifiers;
				this.requires[i] = ref;
			}
		} else {
			this.requires = new ModuleReferenceImpl[0];
		}
		if (descriptor.exportsCount > 0) {
			ExportsStatement[] refs = descriptor.exports;
			this.exports = new PackageExportImpl[refs.length];
			for (int i = 0; i < refs.length; i++) {
				PackageExportImpl exp = createPackageExport(refs, i);
				this.exports[i] = exp;
			}
		} else {
			this.exports = new PackageExportImpl[0];
		}
		if (descriptor.usesCount > 0) {
			UsesStatement[] u = descriptor.uses;
			this.uses = new char[u.length][];
			for(int i = 0; i < u.length; i++) {
				this.uses[i] = CharOperation.concatWith(u[i].serviceInterface.getTypeName(), '.');
			}
		}
		if (descriptor.servicesCount > 0) {
			ProvidesStatement[] services = descriptor.services;
			this.provides = new Service[descriptor.servicesCount];
			for (int i = 0; i < descriptor.servicesCount; i++) {
				this.provides[i] = createService(services[i].serviceInterface, services[i].implementations);
			}
		}
		if (descriptor.opensCount > 0) {
			OpensStatement[] refs = descriptor.opens;
			this.opens = new PackageExportImpl[refs.length];
			for (int i = 0; i < refs.length; i++) {
				PackageExportImpl exp = createPackageOpen(refs[i]);
				this.opens[i] = exp;
			}
		} else {
			this.opens = new PackageExportImpl[0];
		}
		this.isAutomodule = false; // Just to be explicit
		this.isOpen = descriptor.isOpen();
	}
	public BasicModule(char[] name, boolean isAuto) {
		this.name = name;
		this.exports = IModule.NO_EXPORTS;
		this.requires = IModule.NO_MODULE_REFS;
		this.isAutomodule = isAuto;
	}
	@Override
	public char[] name() {
		return this.name;
	}
	@Override
	public IModule.IModuleReference[] requires() {
		return this.requires;
	}
	@Override
	public IModule.IPackageExport[] exports() {
		return this.exports;
	}
	@Override
	public char[][] uses() {
		return this.uses;
	}
	@Override
	public IService[] provides() {
		return this.provides;
	}
	@Override
	public IModule.IPackageExport[] opens() {
		return this.opens;
	}
	@Override
	public boolean isAutomatic() {
		return this.isAutomodule;
	}
	@Override
	public boolean isOpen() {
		return this.isOpen;
	}
	public void addReads(char[] modName) {
		Predicate shouldAdd = m -> {
			return Stream.of(this.requires).map(ref -> ref.name()).noneMatch(n -> CharOperation.equals(modName, n));
		};
		if (shouldAdd.test(modName)) {
			int len = this.requires.length;
			this.requires = Arrays.copyOf(this.requires, len + 1);
			ModuleReferenceImpl info = new ModuleReferenceImpl();
			info.name = modName;
			this.requires[len] = info;
		}		
	}
	public void addExports(IModule.IPackageExport[] toAdd) {
		Predicate shouldAdd = m -> {
			return Stream.of(this.exports).map(ref -> ((PackageExportImpl) ref).pack).noneMatch(n -> CharOperation.equals(m, n));
		};
		Collection merged = Stream.concat(Stream.of(this.exports), Stream.of(toAdd)
				.filter(e -> shouldAdd.test(e.name()))
				.map(e -> {
					PackageExportImpl exp = new PackageExportImpl();
					exp.pack = ((PackageExportImpl )e).name();
					exp.exportedTo = ((PackageExportImpl )e).targets();
					return exp;
				}))
			.collect(
				ArrayList::new,
				ArrayList::add,
				ArrayList::addAll);
		this.exports = merged.toArray(new PackageExportImpl[merged.size()]);
	}
	public boolean equals(Object o) {
		if (this == o)
			return true;
		if (!(o instanceof IModule))
			return false;
		IModule mod = (IModule) o;
		if (!CharOperation.equals(this.name, mod.name()))
			return false;
		return Arrays.equals(this.requires, mod.requires());
	}
	@Override
	public int hashCode() {
		int result = 17;
		int c = this.name.hashCode();
		result = 31 * result + c;
		c =  Arrays.hashCode(this.requires);
		result = 31 * result + c;
		return result;
	}
	public String toString() {
		StringBuffer buffer = new StringBuffer(getClass().getName());
		toStringContent(buffer);
		return buffer.toString();
	}
	protected void toStringContent(StringBuffer buffer) {
		buffer.append("\nmodule "); //$NON-NLS-1$
		buffer.append(this.name).append(' ');
		buffer.append('{').append('\n');
		if (this.requires != null) {
			for(int i = 0; i < this.requires.length; i++) {
				buffer.append("\trequires "); //$NON-NLS-1$
				if (this.requires[i].isTransitive()) {
					buffer.append(" public "); //$NON-NLS-1$
				}
				buffer.append(this.requires[i].name());
				buffer.append(';').append('\n');
			}
		}
		if (this.exports != null) {
			buffer.append('\n');
			for(int i = 0; i < this.exports.length; i++) {
				buffer.append("\texports "); //$NON-NLS-1$
				buffer.append(this.exports[i].toString());
			}
		}
		if (this.uses != null) {
			buffer.append('\n');
			for (char[] cs : this.uses) {
				buffer.append(cs);
				buffer.append(';').append('\n');
			}
		}
		if (this.provides != null) {
			buffer.append('\n');
			for(Service ser : this.provides) {
				buffer.append(ser.toString());
			}
		}
		buffer.append('\n').append('}').toString();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy