forked from microbean/microbean-construct
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPrimordialDomain.java
More file actions
145 lines (135 loc) · 5.37 KB
/
PrimordialDomain.java
File metadata and controls
145 lines (135 loc) · 5.37 KB
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
/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
*
* Copyright © 2025–2026 microBean™.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.microbean.construct;
import javax.lang.model.element.Name;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.NoType;
import javax.lang.model.type.NullType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import org.microbean.construct.element.StringName;
import org.microbean.construct.element.SyntheticName;
/**
* A view of an underlying domain of valid Java constructs that exposes {@linkplain #nullType() the null type}, various
* kinds of {@linkplain #noType(TypeKind) pseudo-types}, the {@linkplain #javaLangObjectType() prototypical
* <code>java.lang.Object</code> type}, and the ability to {@linkplain #lock() globally lock for symbol completion if
* needed}.
*
* <p>{@link PrimordialDomain}s are primordial because they expose the "first principles" constructs needed to compose
* other constructs.</p>
*
* @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a>
*
* @see #javaLangObjectType()
*
* @see #lock()
*
* @see #noType(TypeKind)
*
* @see #nullType()
*
* @see Domain
*/
public interface PrimordialDomain {
/**
* Returns the (non-{@code null}, determinate) {@link DeclaredType} representing the <a
* href="https://docs.oracle.com/en/java/javase/25/docs/api/java.compiler/javax/lang/model/element/TypeElement.html#prototypicaltype"><dfn>prototypical
* type</dfn></a> of {@link Object java.lang.Object}.
*
* <p>Implementations of this method must not return {@code null}.</p>
*
* <p>{@link DeclaredType} instances returned by implementations of this method must return {@link TypeKind#DECLARED}
* from their {@link TypeMirror#getKind()} method.</p>
*
* @return the {@link DeclaredType} representing the <dfn>prototypical type</dfn> of {@link Object java.lang.Object};
* never {@code null}
*/
public DeclaredType javaLangObjectType();
/**
* Semantically locks an opaque lock used to serialize symbol completion, and returns it in the form of an {@link
* Unlockable}.
*
* <p>Implementations of this method must not return {@code null}.</p>
*
* @return an {@link Unlockable} in a semantically locked state; never {@code null}
*
* @see SymbolCompletionLock
*
* @see Unlockable#close()
*/
public Unlockable lock();
/**
* Returns a (non-{@code null}, determinate) {@link NoType} representing the supplied {@link TypeKind}, provided it is
* either {@link TypeKind#NONE} or {@link TypeKind#VOID}.
*
* <p>Implementations of this method must not return {@code null}.</p>
*
* @param kind a {@link TypeKind}; must be either {@link TypeKind#NONE} or {@link TypeKind#VOID}
*
* @return a {@link NoType} representing the supplied {@link TypeKind}; never {@code null}
*
* @exception NullPointerException if {@code kind} is {@code null}
*
* @exception IllegalArgumentException if {@code kind} is neither {@link TypeKind#NONE} nor {@link TypeKind#VOID}
*
* @see javax.lang.model.util.Types#getNoType(TypeKind)
*/
public NoType noType(final TypeKind kind);
/**
* Returns a (non-{@code null}, determinate) {@link NullType} representing the null type.
*
* <p>Implementations of this method must not return {@code null}.</p>
*
* @return a {@link NullType} representing the null type; never {@code null}
*
* @see javax.lang.model.util.Types#getNullType()
*/
public NullType nullType();
/**
* A convenience method that converts the supplied {@link CharSequence}, which is often a {@link Name}, into a {@link
* String}, and returns the conversion, {@linkplain #lock() locking} when appropriate to serialize symbol completion.
*
* <p>The default implementation of this method may return {@code null} if the supplied {@code name} is {@code
* null}.</p>
*
* <p>In many implementations of {@link PrimordialDomain}s, converting a {@link Name} to a {@link String} can cause
* problems if symbol completion is taking place concurrently and the symbol completion lock is not held. This method
* helps avoid those problems.</p>
*
* <p>Overriding this method is not normally needed.</p>
*
* @param name the {@link CharSequence} to convert; may be {@code null} in which case {@code null} will be returned
*
* @return a {@link String}, or {@code null} if {@code name} was {@code null}
*
* @see #lock()
*
* @see Name
*/
@SuppressWarnings("try")
public default String toString(final CharSequence name) {
return switch (name) {
case null -> null;
case String s -> s;
case StringName sn -> sn.value();
case SyntheticName sn -> sn.toString();
case Name n -> {
try (var lock = this.lock()) {
yield n.toString();
}
}
default -> name.toString();
};
}
}