-
Notifications
You must be signed in to change notification settings - Fork 724
Expand file tree
/
Copy pathJVariableSymbol.java
More file actions
176 lines (149 loc) · 4.79 KB
/
Copy pathJVariableSymbol.java
File metadata and controls
176 lines (149 loc) · 4.79 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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
* SonarQube Java
* Copyright (C) SonarSource Sàrl
* mailto:info AT sonarsource DOT com
*
* You can redistribute and/or modify this program under the terms of
* the Sonar Source-Available License Version 1, as published by SonarSource Sàrl.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Sonar Source-Available License for more details.
*
* You should have received a copy of the Sonar Source-Available License
* along with this program; if not, see https://sonarsource.com/license/ssal/
*/
package org.sonar.java.model;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nullable;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.sonar.plugins.java.api.semantic.Symbol;
import org.sonar.plugins.java.api.semantic.SymbolMetadata;
import org.sonar.plugins.java.api.semantic.Type;
import org.sonar.plugins.java.api.tree.IdentifierTree;
import org.sonar.plugins.java.api.tree.VariableTree;
final class JVariableSymbol extends JSymbol implements Symbol.VariableSymbol {
// cache for this.constantValue()
private boolean constantValueComputed = false;
private Optional<Object> constantValue;
JVariableSymbol(JSema sema, IVariableBinding variableBinding) {
super(sema, variableBinding);
}
@Nullable
@Override
public VariableTree declaration() {
return (VariableTree) super.declaration();
}
@Override
public boolean isEffectivelyFinal() {
return ((IVariableBinding)binding).isEffectivelyFinal();
}
@Override
public Optional<Object> constantValue() {
if (!constantValueComputed) {
constantValueComputed = true;
if (!isFinal() || !isStatic()) {
constantValue = Optional.empty();
} else {
Object c = ((IVariableBinding) binding).getConstantValue();
if (c instanceof Short shortValue) {
c = Integer.valueOf(shortValue);
} else if (c instanceof Byte byteValue) {
c = Integer.valueOf(byteValue);
} else if (c instanceof Character characterValue) {
c = Integer.valueOf(characterValue);
}
constantValue = Optional.ofNullable(c);
}
}
return constantValue;
}
@Override
public boolean isLocalVariable() {
Symbol owner = owner();
return owner != null && owner.isMethodSymbol();
}
@Override
public boolean isParameter() {
return ((IVariableBinding) binding).isParameter();
}
static class ParameterPlaceholderSymbol extends Symbols.DefaultSymbol implements Symbol.VariableSymbol {
private final String name;
private final Symbol owner;
private final Type type;
private final SymbolMetadata metadata;
/**
* @param typeBinding the type of the parameter at the call site, after type substitution
* @param declaredTypeBinding the type of the parameter as declared, before type substitution. Annotations are read from it, so that
* annotations inferred for a type variable are not mistaken for annotations of the parameter itself.
*/
ParameterPlaceholderSymbol(int index, JSema sema, IMethodBinding owner, ITypeBinding typeBinding, ITypeBinding declaredTypeBinding) {
this.name = "arg" + index;
this.owner = sema.methodSymbol(owner);
this.type = sema.type(typeBinding);
this.metadata = JSymbolMetadata.of(sema, this, declaredTypeBinding, owner.getParameterAnnotations(index));
}
@Override
public String name() {
return name;
}
@Override
public Symbol owner() {
return owner;
}
@Override
public Type type() {
return type;
}
@Override
public boolean isUnknown() {
return false;
}
@Override
public TypeSymbol enclosingClass() {
return owner.enclosingClass();
}
@Override
public List<IdentifierTree> usages() {
return Collections.emptyList();
}
@Override
public VariableTree declaration() {
return null;
}
@Override
public boolean isEffectivelyFinal() {
return false;
}
@Override
public Optional<Object> constantValue() {
return Optional.empty();
}
@Override
public boolean isLocalVariable() {
return false;
}
@Override
public boolean isParameter() {
return true;
}
@Override
public SymbolMetadata metadata() {
return metadata;
}
@Override
public boolean isVariableSymbol() {
return true;
}
@Override
public boolean isFinal() {
// From a caller perspective, it is not useful (and even not possible) to know if the parameter is final.
return false;
}
}
}