-
Notifications
You must be signed in to change notification settings - Fork 51
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
On error validation #289
base: main
Are you sure you want to change the base?
On error validation #289
Changes from all commits
bf3922a
96b066f
81aaf84
0fcd03b
a82599a
07a499a
f442a2a
310ff12
a348622
ad91a56
aff20e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ | |
package org.eclipse.lsp4jakarta.jdt.core.websocket; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
|
@@ -77,13 +78,16 @@ public void collectDiagnostics(ICompilationUnit unit, List<Diagnostic> diagnosti | |
// checks if the class uses annotation to create a WebSocket endpoint | ||
if (checkWSEnd.get(WebSocketConstants.IS_ANNOTATION)) { | ||
// WebSocket Invalid Parameters Diagnostic | ||
invalidParamsCheck(type, WebSocketConstants.ON_OPEN, WebSocketConstants.ON_OPEN_PARAM_OPT_TYPES, | ||
WebSocketConstants.RAW_ON_OPEN_PARAM_OPT_TYPES, | ||
WebSocketConstants.DIAGNOSTIC_CODE_ON_OPEN_INVALID_PARAMS, unit, diagnostics); | ||
invalidParamsCheck(type, WebSocketConstants.ON_CLOSE, WebSocketConstants.ON_CLOSE_PARAM_OPT_TYPES, | ||
WebSocketConstants.RAW_ON_CLOSE_PARAM_OPT_TYPES, | ||
WebSocketConstants.DIAGNOSTIC_CODE_ON_CLOSE_INVALID_PARAMS, unit, diagnostics); | ||
|
||
invalidParamsCheck(type, WebSocketConstants.ON_OPEN, WebSocketConstants.ON_OPEN_PARAM_OPT_TYPES, | ||
WebSocketConstants.RAW_ON_OPEN_PARAM_OPT_TYPES, WebSocketConstants.DIAGNOSTIC_CODE_ON_OPEN_INVALID_PARAMS, | ||
Collections.emptySet(), Collections.emptySet(), unit, diagnostics); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. might be a bit more space-efficient to pass in null instead of empty sets here and then have a check in the function? |
||
invalidParamsCheck(type, WebSocketConstants.ON_CLOSE, WebSocketConstants.ON_CLOSE_PARAM_OPT_TYPES, | ||
WebSocketConstants.RAW_ON_CLOSE_PARAM_OPT_TYPES, WebSocketConstants.DIAGNOSTIC_CODE_ON_CLOSE_INVALID_PARAMS, | ||
Collections.emptySet(), Collections.emptySet(), unit, diagnostics); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same as above for empty sets |
||
invalidParamsCheck(type, WebSocketConstants.ON_ERROR, WebSocketConstants.ON_ERROR_PARAM_OPT_TYPES, | ||
WebSocketConstants.RAW_ON_ERROR_PARAM_OPT_TYPES, WebSocketConstants.DIAGNOSTIC_CODE_ON_ERROR_INVALID_PARAMS, | ||
WebSocketConstants.ON_ERROR_PARAM_MAND_TYPES, WebSocketConstants.RAW_ON_ERROR_PARAM_MAND_TYPES, unit, diagnostics); | ||
|
||
// PathParam URI Mismatch Warning Diagnostic | ||
uriMismatchWarningCheck(type, diagnostics, unit); | ||
// ServerEndpoint annotation diagnostics | ||
|
@@ -95,9 +99,8 @@ public void collectDiagnostics(ICompilationUnit unit, List<Diagnostic> diagnosti | |
} | ||
} | ||
|
||
private void invalidParamsCheck(IType type, String methodAnnotTarget, Set<String> specialParamTypes, | ||
Set<String> rawSpecialParamTypes, String diagnosticCode, ICompilationUnit unit, | ||
List<Diagnostic> diagnostics) throws JavaModelException { | ||
private void invalidParamsCheck(IType type, String methodAnnotTarget, Set<String> specialParamTypes, Set<String> rawSpecialParamTypes, String diagnosticCode, | ||
Set<String> mandParamTypes, Set<String> rawMandParamTypes, ICompilationUnit unit, List<Diagnostic> diagnostics) throws JavaModelException { | ||
|
||
IMethod[] allMethods = type.getMethods(); | ||
|
||
|
@@ -107,6 +110,9 @@ private void invalidParamsCheck(IType type, String methodAnnotTarget, Set<String | |
for (IAnnotation annotation : allAnnotations) { | ||
if (annotation.getElementName().equals(methodAnnotTarget)) { | ||
ILocalVariable[] allParams = method.getParameters(); | ||
HashMap<String, ILocalVariable> mandTypeCounter = initializeHashMap(mandParamTypes); | ||
HashMap<String, ILocalVariable> rawMandTypeCounter = initializeHashMap(rawMandParamTypes); | ||
Boolean isResolvedType = false; | ||
|
||
for (ILocalVariable param : allParams) { | ||
String signature = param.getTypeSignature(); | ||
|
@@ -116,21 +122,56 @@ private void invalidParamsCheck(IType type, String methodAnnotTarget, Set<String | |
boolean isPrimitive = JavaModelUtil.isPrimitive(formatSignature); | ||
boolean isSpecialType; | ||
boolean isPrimWrapped; | ||
boolean isMandParam; | ||
|
||
// general paramType | ||
String genParamType; | ||
Set<String> genSpecialParamTypes; | ||
Set<String> genMandParamTypes; | ||
HashMap<String, ILocalVariable> genMandTypeCounter; | ||
|
||
if (resolvedTypeName != null) { | ||
isSpecialType = specialParamTypes.contains(resolvedTypeName); | ||
isPrimWrapped = isWrapper(resolvedTypeName); | ||
genParamType = resolvedTypeName; | ||
genSpecialParamTypes = specialParamTypes; | ||
genMandParamTypes = mandParamTypes; | ||
isResolvedType = true; | ||
genMandTypeCounter = mandTypeCounter; | ||
} else { | ||
String simpleParamType = Signature.getSignatureSimpleName(signature); | ||
isSpecialType = rawSpecialParamTypes.contains(simpleParamType); | ||
isPrimWrapped = isWrapper(simpleParamType); | ||
genParamType = simpleParamType; | ||
genSpecialParamTypes = rawSpecialParamTypes; | ||
genMandParamTypes = rawMandParamTypes; | ||
genMandTypeCounter = rawMandTypeCounter; | ||
} | ||
|
||
isSpecialType = genSpecialParamTypes.contains(genParamType); | ||
isPrimWrapped = isWrapper(genParamType); | ||
isMandParam = genMandParamTypes.contains(genParamType); | ||
|
||
if (isMandParam) { | ||
if (genMandTypeCounter.get(genParamType) != null) { | ||
String diagMsg = createParamTypeDiagMsg(WebSocketConstants.DIAGNOSTIC_DUP_PARAMS_TYPES, | ||
methodAnnotTarget, specialParamTypes, mandParamTypes); | ||
Diagnostic diagnostic = createDiagnostic(param, unit, | ||
diagMsg, WebSocketConstants.DIAGNOSTIC_CODE_DUP_PARAMS_TYPES); | ||
diagnostics.add(diagnostic); | ||
|
||
Diagnostic diagnostic2 = createDiagnostic(genMandTypeCounter.get(genParamType), unit, | ||
diagMsg, WebSocketConstants.DIAGNOSTIC_CODE_DUP_PARAMS_TYPES); | ||
diagnostics.add(diagnostic2); | ||
continue; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. redundant continue |
||
} else { | ||
genMandTypeCounter.put(genParamType, param); | ||
} | ||
continue; | ||
} | ||
|
||
// check parameters valid types | ||
if (!(isSpecialType || isPrimWrapped || isPrimitive)) { | ||
String diagMessage = createParamTypeDiagMsg(WebSocketConstants.PARAM_TYPE_DIAG_MSG, | ||
methodAnnotTarget, specialParamTypes, mandParamTypes); | ||
Diagnostic diagnostic = createDiagnostic(param, unit, | ||
createParamTypeDiagMsg(specialParamTypes, methodAnnotTarget), | ||
diagnosticCode); | ||
diagMessage, diagnosticCode); | ||
diagnostics.add(diagnostic); | ||
continue; | ||
} | ||
|
@@ -149,11 +190,38 @@ private void invalidParamsCheck(IType type, String methodAnnotTarget, Set<String | |
} | ||
} | ||
} | ||
|
||
HashMap<String, ILocalVariable> genMandTypeCounter = isResolvedType ? mandTypeCounter : rawMandTypeCounter; | ||
|
||
// check that all mandatory parameters are present | ||
for (HashMap.Entry<String, ILocalVariable> entry : genMandTypeCounter.entrySet()) { | ||
if (entry.getValue() == null) { | ||
String diagMessage = createParamTypeDiagMsg(WebSocketConstants.DIAGNOSTIC_MAND_PARAMS_MISSING, | ||
methodAnnotTarget, Collections.emptySet(), mandParamTypes); | ||
Diagnostic diagnostic = createDiagnostic(method, unit, | ||
diagMessage, WebSocketConstants.DIAGNOSTIC_CODE_ON_ERROR_MAND_PARAMS_MISS); | ||
diagnostics.add(diagnostic); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Creates a hashmap with the given set of keys and initializes the values to null. | ||
* @param types set of parameter types | ||
* @return hashmap with keys initialized to types | ||
*/ | ||
private HashMap<String, ILocalVariable> initializeHashMap(Set<String> types) { | ||
HashMap<String, ILocalVariable> numTypes = new HashMap<>(); | ||
for (String type : types) { | ||
numTypes.put(type, null); | ||
} | ||
return numTypes; | ||
} | ||
|
||
/** | ||
* Creates a warning diagnostic if a PathParam annotation does not match any | ||
* variable parameters of the WebSocket EndPoint URI associated with the class | ||
|
@@ -295,7 +363,7 @@ private List<String> findAndProcessEndpointURI(IType type) throws JavaModelExcep | |
} | ||
|
||
/** | ||
* Check if valueClass is a wrapper object for a primitive value Based on | ||
* Check if valueClass is a wrapper object for a primitive value. Based on | ||
* https://github.com/eclipse/lsp4mp/blob/9789a1a996811fade43029605c014c7825e8f1da/microprofile.jdt/org.eclipse.lsp4mp.jdt.core/src/main/java/org/eclipse/lsp4mp/jdt/core/utils/JDTTypeUtils.java#L294-L298 | ||
* | ||
* @param valueClass the resolved type of valueClass in string or the simple | ||
|
@@ -348,9 +416,21 @@ private HashMap<String, Boolean> isWSEndpoint(IType type) throws JavaModelExcept | |
return wsEndpoint; | ||
} | ||
|
||
private String createParamTypeDiagMsg(Set<String> methodParamOptTypes, String methodAnnotTarget) { | ||
/** | ||
* Creates a diagnotic message for parameter types that are not supported by | ||
* @param initialMsg the initial message to be displayed | ||
* @param methodAnnotTarget the annotation target of the method | ||
* @param methodParamOptTypes the optional parameter types of the method | ||
* @param mandParamTypes the mandatory parameter types of the method | ||
* @return the final diagnostic message | ||
*/ | ||
private String createParamTypeDiagMsg(String initialMsg, String methodAnnotTarget, Set<String> methodParamOptTypes, Set<String> mandParamTypes) { | ||
String paramMessage = String.join("\n- ", methodParamOptTypes); | ||
return String.format(WebSocketConstants.PARAM_TYPE_DIAG_MSG, "@" + methodAnnotTarget, paramMessage); | ||
|
||
if (mandParamTypes.size() > 0) { | ||
paramMessage += (methodParamOptTypes.size() > 0 ? "\n- " : "") + String.join("\n- ", mandParamTypes); | ||
} | ||
return String.format(initialMsg, "@" + methodAnnotTarget, paramMessage); | ||
} | ||
|
||
/** | ||
|
@@ -384,3 +464,4 @@ private boolean hasDuplicateURIVariables(String uriString) { | |
return false; | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package io.openliberty.sample.jakarta.websocket; | ||
|
||
import java.lang.Throwable; | ||
|
||
import jakarta.websocket.OnError; | ||
import jakarta.websocket.server.ServerEndpoint; | ||
|
||
/** | ||
* Expected Diagnostics are related to validating that the parameters for the onError | ||
* WebSocket method are not duplicate (diagnostic code: OnErrorChangeInvalidParam). | ||
* See issue #249 (OnError) | ||
*/ | ||
@ServerEndpoint(value = "/infos") | ||
public class DuplicateParamCheck { | ||
@OnError | ||
public void OnError(Session session, Throwable error1, Throwable error2) throws IOException { | ||
System.out.println("WebSocket closed for " + session.getId()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package io.openliberty.sample.jakarta.websocket; | ||
|
||
import jakarta.websocket.OnError; | ||
import jakarta.websocket.server.ServerEndpoint; | ||
|
||
/** | ||
* Expected Diagnostics are related to validating that the parameters for the | ||
* OnError WebSocket methods are not duplicate values | ||
* (diagnostic code: OnErrorMandatoryParamMissing). See issues #249 (OnError) | ||
*/ | ||
@ServerEndpoint(value = "/infos") | ||
public class MandatoryParamTypes { | ||
@OnError | ||
public void OnError(Session session) throws IOException { | ||
System.out.println("WebSocket closed for " + session.getId()); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect if you pull the latest changes from main, you'll be able to use the defined strings for these hashsets.