Skip to main content
summaryrefslogtreecommitdiffstats
blob: 0704eefe9ff1b640564d45b097a43b080f4b86aa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*******************************************************************************
 * Copyright (c) 2017, 2018 GK Software AG, and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Stephan Herrmann - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.env;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray;

/**
 * Interface to a module as needed to implement the updates for {@code --add-reads}
 * and {@code --add-exports} command line options (or corresponding classpath attributes).
 */
public interface IUpdatableModule {

	/**
	 * The compiler first wires modules only, before then wiring packages based on the module graph.
	 * This enum selects one of these phases when asking the environment to perform its updates.
	 */
	enum UpdateKind { MODULE, PACKAGE }

	class AddExports implements Consumer<IUpdatableModule> {

		char[] name;
		char[][] targets;
		public AddExports(char[] pkgName, char[][] targets) {
			this.name = pkgName;
			this.targets = targets;
		}
		@Override
		public void accept(IUpdatableModule t) {
			t.addExports(this.name, this.targets);
		}
		
		public char[] getName() {
			return this.name;
		}
		
		public char[][] getTargetModules() {
			return this.targets;
		}
		
		public UpdateKind getKind() {
			return UpdateKind.PACKAGE;
		}
		@Override
		public boolean equals(Object other) {
			if (this == other) return true;
			if (!(other instanceof AddExports)) return false;
			AddExports pu = (AddExports) other;
			
			if (!CharOperation.equals(this.name, pu.name))
				return false;
			if (!CharOperation.equals(this.targets, pu.targets))
				return false;
			return true;
		}
		@Override
		public int hashCode() {
			int hash = CharOperation.hashCode(this.name);
			if (this.targets != null) {
				for (int i = 0; i < this.targets.length; i++) {
					hash += 17 * CharOperation.hashCode(this.targets[i]);
				}
			}
			return hash;
		}
	}
	
	class AddReads implements Consumer<IUpdatableModule> {

		char[] targetModule;
		
		public AddReads(char[] target) {
			this.targetModule = target;
		}
		@Override
		public void accept(IUpdatableModule t) {
			// TODO Auto-generated method stub
			t.addReads(this.targetModule);
		}
		
		public char[] getTarget() {
			return this.targetModule;
		}
		
		public UpdateKind getKind() {
			return UpdateKind.MODULE;
		}

		@Override
		public boolean equals(Object other) {
			if (this == other) return true;
			if (!(other instanceof AddReads)) return false;
			AddReads mu = (AddReads) other;
			return CharOperation.equals(this.targetModule, mu.targetModule);
		}
		@Override
		public int hashCode() {
			return CharOperation.hashCode(this.targetModule);
		}
	}
	/** Structure for update operations, sorted by {@link UpdateKind}. */
	class UpdatesByKind {
		List<Consumer<IUpdatableModule>> moduleUpdates = Collections.emptyList();
		List<Consumer<IUpdatableModule>> packageUpdates = Collections.emptyList();
		public List<Consumer<IUpdatableModule>> getList(UpdateKind kind, boolean create) {
			switch (kind) {
				case MODULE:
					if (this.moduleUpdates == Collections.EMPTY_LIST && create)
						this.moduleUpdates = new ArrayList<>();
					return this.moduleUpdates;
				case PACKAGE:
					if (this.packageUpdates == Collections.EMPTY_LIST && create)
						this.packageUpdates = new ArrayList<>();
					return this.packageUpdates;
				default:
					throw new IllegalArgumentException("Unknown enum value "+kind); //$NON-NLS-1$
			}
		}
	}

	/** Answer the name of the module to update. */
	char[] name();
	/** Perform an --add-reads update on the module. */
	void addReads(char[] moduleName);
	/** Perform an --add-exports update on the module. */
	void addExports(char[] packageName, char[][] targetModules);
	/** Define the ModuleMainClass to be recorded in the generated module-info.class. */
	void setMainClassName(char[] mainClassName);
	/** Passes names of packages to be recorded in the ModulePackages classfile attribute. */
	void setPackageNames(SimpleSetOfCharArray packageNames);
}

Back to the top