Skip to content

Commit 9870eac

Browse files
committed
jsdoc: parameterized type validations
1 parent 892563d commit 9870eac

File tree

8 files changed

+171
-49
lines changed

8 files changed

+171
-49
lines changed

plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/parser/JSDocValidatorFactory.java

Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
package org.eclipse.dltk.internal.javascript.parser;
22

3+
import static org.eclipse.dltk.internal.javascript.validation.JavaScriptValidations.reportValidationStatus;
4+
35
import java.util.ArrayList;
46
import java.util.List;
57
import java.util.StringTokenizer;
68

79
import org.eclipse.core.runtime.Assert;
10+
import org.eclipse.dltk.annotations.Nullable;
811
import org.eclipse.dltk.compiler.problem.IProblemIdentifier;
912
import org.eclipse.dltk.compiler.problem.IValidationStatus;
1013
import org.eclipse.dltk.compiler.problem.ValidationStatus;
1114
import org.eclipse.dltk.core.ISourceNode;
1215
import org.eclipse.dltk.internal.javascript.ti.IReferenceAttributes;
1316
import org.eclipse.dltk.internal.javascript.ti.TypeInferencer2;
14-
import org.eclipse.dltk.internal.javascript.validation.JavaScriptValidations;
1517
import org.eclipse.dltk.internal.javascript.validation.ValidationMessages;
1618
import org.eclipse.dltk.javascript.core.JavaScriptProblems;
1719
import org.eclipse.dltk.javascript.parser.JSProblemReporter;
1820
import org.eclipse.dltk.javascript.parser.jsdoc.JSDocTag;
1921
import org.eclipse.dltk.javascript.typeinference.IValueCollection;
2022
import org.eclipse.dltk.javascript.typeinference.IValueReference;
2123
import org.eclipse.dltk.javascript.typeinference.ReferenceKind;
24+
import org.eclipse.dltk.javascript.typeinfo.ITypeCheck;
2225
import org.eclipse.dltk.javascript.typeinfo.ITypeChecker;
2326
import org.eclipse.dltk.javascript.typeinfo.ITypeCheckerExtension;
2427
import org.eclipse.dltk.javascript.typeinfo.TypeUtil;
2528
import org.eclipse.dltk.javascript.typeinfo.model.AnyType;
2629
import org.eclipse.dltk.javascript.typeinfo.model.ArrayType;
2730
import org.eclipse.dltk.javascript.typeinfo.model.ClassType;
2831
import org.eclipse.dltk.javascript.typeinfo.model.FunctionType;
32+
import org.eclipse.dltk.javascript.typeinfo.model.GenericType;
2933
import org.eclipse.dltk.javascript.typeinfo.model.JSType;
3034
import org.eclipse.dltk.javascript.typeinfo.model.MapType;
3135
import org.eclipse.dltk.javascript.typeinfo.model.Member;
@@ -86,26 +90,58 @@ public void checkType(JSType type, ISourceNode tag, int flags) {
8690
checkType(((MapType) type).getValueType(), tag, flags);
8791
} else if (type instanceof SimpleType) {
8892
if (type instanceof ParameterizedType) {
89-
for (JSType param : ((ParameterizedType) type)
90-
.getActualTypeArguments()) {
93+
final ParameterizedType parameterized = (ParameterizedType) type;
94+
for (JSType param : parameterized.getActualTypeArguments()) {
9195
checkType(param, tag, flags);
9296
}
97+
checkType(((SimpleType) type).getTarget(), tag, flags,
98+
new ITypeCheck[] { new ParameterizedTypeCheck(
99+
parameterized) });
100+
} else {
101+
checkType(((SimpleType) type).getTarget(), tag, flags, null);
93102
}
94-
final Type t = ((SimpleType) type).getTarget();
95-
checkType(t, tag, flags);
96103
} else if (type instanceof ClassType) {
97104
final Type t = ((ClassType) type).getTarget();
98105
if (t == null) {
99106
return;
100107
}
101-
checkType(t, tag, flags);
108+
checkType(t, tag, flags, null);
102109
}
103110
}
104111

105-
public abstract void checkType(Type type, ISourceNode tag, int flags);
112+
public abstract void checkType(Type type, ISourceNode tag, int flags,
113+
@Nullable ITypeCheck[] checks);
106114

107115
}
108116

117+
private static class ParameterizedTypeCheck implements ITypeCheck {
118+
private final ParameterizedType parameterizedType;
119+
120+
public ParameterizedTypeCheck(ParameterizedType parameterizedType) {
121+
this.parameterizedType = parameterizedType;
122+
}
123+
124+
public IValidationStatus checkType(Type type) {
125+
if (type instanceof GenericType) {
126+
final GenericType genericType = (GenericType) type;
127+
if (genericType.getTypeParameters().size() != parameterizedType
128+
.getActualTypeArguments().size()) {
129+
return new ValidationStatus(
130+
JavaScriptProblems.PARAMETERIZED_TYPE_INCORRECT_ARGUMENTS,
131+
NLS.bind(
132+
ValidationMessages.IncorrectNumberOfTypeArguments,
133+
type.getName()));
134+
}
135+
return null;
136+
} else {
137+
return new ValidationStatus(
138+
JavaScriptProblems.NOT_GENERIC_TYPE, NLS.bind(
139+
ValidationMessages.NotGenericType,
140+
type.getName()));
141+
}
142+
}
143+
}
144+
109145
public static class TypeChecker extends AbstractTypeChecker implements
110146
ITypeCheckerExtension {
111147

@@ -125,17 +161,12 @@ public void checkType(JSType type, ISourceNode tag, int flags) {
125161
if (extension instanceof IValidatorExtension2) {
126162
final IValidationStatus status = ((IValidatorExtension2) extension)
127163
.validateTypeExpression(type);
128-
if (status != null) {
129-
if (status == ValidationStatus.OK) {
130-
break;
131-
} else {
132-
JavaScriptValidations.reportValidationStatus(
133-
reporter, status, tag,
134-
JavaScriptProblems.INACCESSIBLE_TYPE,
135-
ValidationMessages.InaccessibleType,
136-
type.getName());
137-
return;
138-
}
164+
if (status != null && status != ValidationStatus.OK) {
165+
reportValidationStatus(reporter, status, tag,
166+
JavaScriptProblems.INACCESSIBLE_TYPE,
167+
ValidationMessages.InaccessibleType,
168+
type.getName());
169+
return;
139170
}
140171
}
141172
}
@@ -144,25 +175,29 @@ public void checkType(JSType type, ISourceNode tag, int flags) {
144175
}
145176

146177
@Override
147-
public void checkType(Type type, ISourceNode tag, int flags) {
178+
public void checkType(Type type, ISourceNode tag, int flags,
179+
@Nullable ITypeCheck[] checks) {
148180
if (type.getKind() == TypeKind.UNKNOWN
149181
|| type.getKind() == TypeKind.UNRESOLVED) {
150182
queue.add(new QueueItem(type, tag, context.currentCollection(),
151-
flags));
183+
flags, checks));
152184
} else {
153185
checkDeprecatedType(type, tag);
186+
if (checks != null) {
187+
doChecks(type, tag, checks);
188+
}
154189
}
155190
}
156191

157192
public void validate() {
158193
for (QueueItem item : queue) {
159-
checkType(item.tag, context.resolveType(item.type),
160-
item.collection, item.flags);
194+
doCheckType(context.resolveType(item.type), item.tag,
195+
item.flags, item.checks, item.collection);
161196
}
162197
}
163198

164-
protected void checkType(ISourceNode tag, Type type,
165-
IValueCollection collection, int flags) {
199+
private void doCheckType(Type type, ISourceNode tag, int flags,
200+
@Nullable ITypeCheck[] checks, IValueCollection collection) {
166201
if (type.eIsProxy()) {
167202
Assert.isTrue(!type.eIsProxy(), "Type \"" + type.getName()
168203
+ "\" is a proxy");
@@ -205,6 +240,20 @@ protected void checkType(ISourceNode tag, Type type,
205240
reportUnknownType(tag, TypeUtil.getName(type));
206241
} else {
207242
checkDeprecatedType(type, tag);
243+
if (checks != null) {
244+
doChecks(type, tag, checks);
245+
}
246+
}
247+
}
248+
249+
private void doChecks(Type type, ISourceNode tag, ITypeCheck[] checks) {
250+
for (ITypeCheck check : checks) {
251+
final IValidationStatus status = check.checkType(type);
252+
if (status != null && status != ValidationStatus.OK) {
253+
reportValidationStatus(reporter, status, tag,
254+
JavaScriptProblems.INACCESSIBLE_TYPE,
255+
ValidationMessages.InaccessibleType, type.getName());
256+
}
208257
}
209258
}
210259

@@ -214,22 +263,18 @@ private void checkDeprecatedType(Type type, ISourceNode tag) {
214263
JavaScriptProblems.DEPRECATED_TYPE,
215264
NLS.bind(ValidationMessages.DeprecatedType,
216265
TypeUtil.getName(type)), tag.start(), tag.end());
266+
return;
217267
} else if (extensions != null) {
218268
for (IValidatorExtension extension : extensions) {
219269
if (extension instanceof IValidatorExtension2) {
220270
final IValidationStatus status = ((IValidatorExtension2) extension)
221271
.validateAccessibility(type);
222-
if (status != null) {
223-
if (status == ValidationStatus.OK) {
224-
return;
225-
} else {
226-
JavaScriptValidations.reportValidationStatus(
227-
reporter, status, tag,
228-
JavaScriptProblems.INACCESSIBLE_TYPE,
229-
ValidationMessages.InaccessibleType,
230-
type.getName());
231-
return;
232-
}
272+
if (status != null && status != ValidationStatus.OK) {
273+
reportValidationStatus(reporter, status, tag,
274+
JavaScriptProblems.INACCESSIBLE_TYPE,
275+
ValidationMessages.InaccessibleType,
276+
type.getName());
277+
return;
233278
}
234279
}
235280
}
@@ -277,13 +322,17 @@ private static class QueueItem {
277322
final ISourceNode tag;
278323
final IValueCollection collection;
279324
final int flags;
325+
@Nullable
326+
final ITypeCheck[] checks;
280327

281328
public QueueItem(Type type, ISourceNode tag,
282-
IValueCollection collection, int flags) {
329+
IValueCollection collection, int flags,
330+
@Nullable ITypeCheck[] checks) {
283331
this.type = type;
284332
this.tag = tag;
285333
this.collection = collection;
286334
this.flags = flags;
335+
this.checks = checks;
287336
}
288337

289338
}

plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/validation/ValidationMessages.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ public class ValidationMessages extends NLS {
7777
public static String UnassignableClass;
7878
public static String UnassignableFunction;
7979

80+
public static String NotGenericType;
81+
public static String IncorrectNumberOfTypeArguments;
82+
8083
static {
8184
// initialize resource bundle
8285
NLS.initializeMessages(BUNDLE_NAME, ValidationMessages.class);

plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/internal/javascript/validation/ValidationMessages.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,6 @@ ReferenceToStaticMethod=The static property {1}.{0} should be accessed in a stat
5959
DeclarationMismatchWithActualReturnType=Function {0} declares {1} as type but returns {2}
6060
DeclarationMismatchNoReturnType=Function {0} declares {1} as type but doesn't return anything
6161
ReturnTypeInconsistentWithPreviousReturn=Return statement returns {0} which is inconsistent with the previous return {1}
62+
63+
NotGenericType=The type {0} is not generic
64+
IncorrectNumberOfTypeArguments=Incorrect number of arguments for type {0}

plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/core/JavaScriptProblems.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,20 @@ public enum JavaScriptProblems implements IProblemIdentifier,
7878
INACCESSIBLE_MEMBER,
7979

8080
/**
81-
* @since 4.1
81+
* @since 5.0
8282
*/
8383
INACCESSIBLE_TYPE,
8484

85+
/**
86+
* @since 5.0
87+
*/
88+
NOT_GENERIC_TYPE,
89+
90+
/**
91+
* @since 5.0
92+
*/
93+
PARAMETERIZED_TYPE_INCORRECT_ARGUMENTS,
94+
8595
/**
8696
* @since 3.0
8797
*/
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2012 NumberFour AG
3+
*
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License v1.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/legal/epl-v10.html
8+
*
9+
* Contributors:
10+
* NumberFour AG - initial API and Implementation (Alex Panchenko)
11+
*******************************************************************************/
12+
package org.eclipse.dltk.javascript.typeinfo;
13+
14+
import org.eclipse.dltk.annotations.Nullable;
15+
import org.eclipse.dltk.compiler.problem.IValidationStatus;
16+
import org.eclipse.dltk.javascript.typeinfo.model.Type;
17+
18+
/**
19+
* Additional type check which could be passed to
20+
* {@link ITypeChecker#checkType(org.eclipse.dltk.javascript.typeinfo.model.Type, org.eclipse.dltk.core.ISourceNode, int, ITypeCheck...)}
21+
* .
22+
*/
23+
public interface ITypeCheck {
24+
25+
@Nullable
26+
IValidationStatus checkType(Type type);
27+
28+
}

plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/typeinfo/ITypeChecker.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.eclipse.dltk.javascript.typeinfo;
22

3+
import org.eclipse.dltk.annotations.Nullable;
34
import org.eclipse.dltk.core.ISourceNode;
45
import org.eclipse.dltk.javascript.typeinfo.model.JSType;
56
import org.eclipse.dltk.javascript.typeinfo.model.Type;
@@ -34,6 +35,9 @@ public interface ITypeChecker {
3435
* @param type
3536
* @param node
3637
* @param flags
38+
* @param checks
39+
* additional checks or <code>null</code> if not required
3740
*/
38-
public void checkType(Type type, ISourceNode node, int flags);
41+
public void checkType(Type type, ISourceNode node, int flags,
42+
@Nullable ITypeCheck[] checks);
3943
}

plugins/org.eclipse.dltk.javascript.core/src/org/eclipse/dltk/javascript/typeinfo/JSDocParseException.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,24 @@
1313

1414
import java.text.ParseException;
1515

16+
import org.eclipse.dltk.compiler.problem.IProblemIdentifier;
1617
import org.eclipse.dltk.javascript.parser.JSProblemIdentifier;
1718

1819
@SuppressWarnings("serial")
1920
public class JSDocParseException extends ParseException {
2021

21-
public final JSProblemIdentifier problemId;
22+
public final IProblemIdentifier problemId;
2223

2324
public JSDocParseException(JSProblemIdentifier problemId, Object... args) {
2425
super(problemId.formatMessage(args), -1);
2526
assert problemId != null;
2627
this.problemId = problemId;
2728
}
2829

30+
public JSDocParseException(String message, IProblemIdentifier problemId) {
31+
super(message, -1);
32+
assert problemId != null;
33+
this.problemId = problemId;
34+
}
35+
2936
}

0 commit comments

Comments
 (0)