Code review comment: Also, this error will be given to the beginning of the function. Check and see if you can give the error to the correct position of the relevant field in the annotation.

Code before review:
public void process(FunctionNode functionNode, List<AnnotationAttachmentNode> annotations) {
if (!enabled) {
return;
}
BLangPackage parent = (BLangPackage) ((BLangFunction) functionNode).parent;
String packageName = getPackageName(parent);
TestSuite suite = registry.getTestSuites().get(packageName);
if (suite == null) {
suite = registry.getTestSuites().computeIfAbsent(packageName, func ->
new TestSuite(parent.packageID.name.value, packageName, parent.packageID.orgName.value,
parent.packageID.version.value));
}
annotations = annotations.stream().distinct().collect(Collectors.toList());
for (AnnotationAttachmentNode attachmentNode : annotations) {
String annotationName = attachmentNode.getAnnotationName().getValue();
String functionName = functionNode.getName().getValue();
if (BEFORE_SUITE_ANNOTATION_NAME.equals(annotationName)) {
suite.addBeforeSuiteFunction(functionName);
} else if (AFTER_SUITE_ANNOTATION_NAME.equals(annotationName)) {
suite.addAfterSuiteFunction(functionName);
} else if (BEFORE_EACH_ANNOTATION_NAME.equals(annotationName)) {
suite.addBeforeEachFunction(functionName);
} else if (AFTER_EACH_ANNOTATION_NAME.equals(annotationName)) {
suite.addAfterEachFunction(functionName);
} else if (MOCK_ANNOTATION_NAME.equals(annotationName)) {
String[] vals = new String[2];
vals[0] = packageName;
if (attachmentNode.getExpression() instanceof BLangRecordLiteral) {
List<RecordLiteralNode.RecordField> attributes = ((BLangRecordLiteral) attachmentNode
.getExpression()).getFields();
attributes.forEach(field -> {
String name;
BLangExpression valueExpr;
if (field.isKeyValueField()) {
BLangRecordLiteral.BLangRecordKeyValueField attributeNode =
(BLangRecordLiteral.BLangRecordKeyValueField) field;
name = attributeNode.getKey().toString();
valueExpr = attributeNode.getValue();
} else {
BLangRecordLiteral.BLangRecordVarNameField varNameField =
(BLangRecordLiteral.BLangRecordVarNameField) field;
name = varNameField.variableName.value;
valueExpr = varNameField;
}
String value = valueExpr.toString();
if (MODULE.equals(name)) {
vals[0] = value;
} else if (FUNCTION.equals(name)) {
vals[1] = value;
}
});
if (bLangPackage == null) {
setBlangPackage(attachmentNode);
}
if (vals[0].isEmpty()) {
diagnosticLog.logDiagnostic(Diagnostic.Kind.ERROR, ((BLangFunction) functionNode).pos,
"Module name cannot be empty");
}
if (vals[1].isEmpty()) {
diagnosticLog.logDiagnostic(Diagnostic.Kind.ERROR, ((BLangFunction) functionNode).pos,
"Function name cannot be empty");
}
SymbolTable symbolTable = SymbolTable.getInstance(compilerContext);
Map<BPackageSymbol, SymbolEnv> packageEnvironmentMap = symbolTable.pkgEnvMap;
PackageID functionToMockID = getPackageID(vals[0], packageEnvironmentMap);
BType functionToMockType = getFunctionType(packageEnvironmentMap, functionToMockID, vals[1]);
BType mockFunctionType = getFunctionType(packageEnvironmentMap, bLangPackage.packageID,
((BLangFunction) functionNode).name.toString());
if (functionToMockType != null && mockFunctionType != null) {
if (!typeChecker.isAssignable(mockFunctionType, functionToMockType)) {
diagnosticLog.logDiagnostic(Diagnostic.Kind.ERROR, ((BLangFunction) functionNode).pos,
"Function parameters and Mock function parameters do not match. Expected "
+ functionToMockType.toString());
}
} else {
diagnosticLog.logDiagnostic(Diagnostic.Kind.ERROR, ((BLangFunction) functionNode).pos,
"Module " + vals[0] + " not found");
}
BLangTestablePackage bLangTestablePackage =
(BLangTestablePackage) ((BLangFunction) functionNode).parent;
bLangTestablePackage.addMockFunction(vals[0] + MOCK_ANNOTATION_DELIMITER + vals[1],
functionName);
}
} else if (TEST_ANNOTATION_NAME.equals(annotationName)) {
Test test = new Test();
test.setTestName(functionName);
AtomicBoolean shouldSkip = new AtomicBoolean();
AtomicBoolean groupsFound = new AtomicBoolean();
List<String> groups = registry.getGroups();
boolean shouldIncludeGroups = registry.shouldIncludeGroups();
if (attachmentNode.getExpression() instanceof BLangRecordLiteral) {
List<RecordLiteralNode.RecordField> attributes = ((BLangRecordLiteral) attachmentNode
.getExpression()).getFields();
attributes.forEach(field -> {
String name;
BLangExpression valueExpr;
if (field.isKeyValueField()) {
BLangRecordLiteral.BLangRecordKeyValueField attributeNode =
(BLangRecordLiteral.BLangRecordKeyValueField) field;
name = attributeNode.getKey().toString();
valueExpr = attributeNode.getValue();
} else {
BLangRecordLiteral.BLangRecordVarNameField varNameField =
(BLangRecordLiteral.BLangRecordVarNameField) field;
name = varNameField.variableName.value;
valueExpr = varNameField;
}
if (TEST_ENABLE_ANNOTATION_NAME.equals(name) && "false".equals(valueExpr
.toString())) {
shouldSkip.set(true);
return;
}
if (GROUP_ANNOTATION_NAME.equals(name)) {
if (valueExpr instanceof BLangListConstructorExpr) {
BLangListConstructorExpr values = (BLangListConstructorExpr) valueExpr;
test.setGroups(values.exprs.stream().map(node -> node.toString())
.collect(Collectors.toList()));
if (groups != null && !groups.isEmpty()) {
boolean isGroupPresent = isGroupAvailable(groups, test.getGroups());
if (shouldIncludeGroups) {
if (!isGroupPresent) {
shouldSkip.set(true);
return;
}
} else {
if (isGroupPresent) {
shouldSkip.set(true);
return;
}
}
groupsFound.set(true);
}
}
}
if (VALUE_SET_ANNOTATION_NAME.equals(name)) {
test.setDataProvider(valueExpr.toString());
}
if (BEFORE_FUNCTION.equals(name)) {
test.setBeforeTestFunction(valueExpr.toString());
}
if (AFTER_FUNCTION.equals(name)) {
test.setAfterTestFunction(valueExpr.toString());
}
if (DEPENDS_ON_FUNCTIONS.equals(name)) {
if (valueExpr instanceof BLangListConstructorExpr) {
BLangListConstructorExpr values = (BLangListConstructorExpr) valueExpr;
values.exprs.stream().map(node -> node.toString()).forEach
(test::addDependsOnTestFunction);
}
}
});
}
if (groups != null && !groups.isEmpty() && !groupsFound.get() && shouldIncludeGroups) {
shouldSkip.set(true);
}
if (!shouldSkip.get()) {
suite.addTests(test);
}
} else {
}
}
}

Line under review: "Module name cannot be empty");

Code after addressing the review:
public void process(FunctionNode functionNode, List<AnnotationAttachmentNode> annotations) {
if (!enabled) {
return;
}
parent = (BLangPackage) ((BLangFunction) functionNode).parent;
String packageName = getPackageName(parent);
TestSuite suite = registry.getTestSuites().get(packageName);
if (suite == null) {
suite = registry.getTestSuites().computeIfAbsent(packageName, func ->
new TestSuite(parent.packageID.name.value, packageName, parent.packageID.orgName.value,
parent.packageID.version.value));
}
annotations = annotations.stream().distinct().collect(Collectors.toList());
for (AnnotationAttachmentNode attachmentNode : annotations) {
String annotationName = attachmentNode.getAnnotationName().getValue();
String functionName = functionNode.getName().getValue();
if (BEFORE_SUITE_ANNOTATION_NAME.equals(annotationName)) {
suite.addBeforeSuiteFunction(functionName);
} else if (AFTER_SUITE_ANNOTATION_NAME.equals(annotationName)) {
suite.addAfterSuiteFunction(functionName);
} else if (BEFORE_EACH_ANNOTATION_NAME.equals(annotationName)) {
suite.addBeforeEachFunction(functionName);
} else if (AFTER_EACH_ANNOTATION_NAME.equals(annotationName)) {
suite.addAfterEachFunction(functionName);
} else if (MOCK_ANNOTATION_NAME.equals(annotationName)) {
String[] vals = new String[2];
vals[0] = packageName;
if (attachmentNode.getExpression() instanceof BLangRecordLiteral) {
List<RecordLiteralNode.RecordField> attributes = ((BLangRecordLiteral) attachmentNode
.getExpression()).getFields();
attributes.forEach(field -> {
String name;
BLangExpression valueExpr;
if (field.isKeyValueField()) {
BLangRecordLiteral.BLangRecordKeyValueField attributeNode =
(BLangRecordLiteral.BLangRecordKeyValueField) field;
name = attributeNode.getKey().toString();
valueExpr = attributeNode.getValue();
} else {
BLangRecordLiteral.BLangRecordVarNameField varNameField =
(BLangRecordLiteral.BLangRecordVarNameField) field;
name = varNameField.variableName.value;
valueExpr = varNameField;
}
String value = valueExpr.toString();
if (MODULE.equals(name)) {
value = formatPackageName(value);
vals[0] = value;
} else if (FUNCTION.equals(name)) {
vals[1] = value;
}
});
if (vals[1].isEmpty()) {
diagnosticLog.logDiagnostic(Diagnostic.Kind.ERROR, attachmentNode.getPosition(),
"function name cannot be empty");
break;
}
PackageID functionToMockID = getPackageID(vals[0]);
if (functionToMockID == null) {
diagnosticLog.logDiagnostic(Diagnostic.Kind.ERROR, attachmentNode.getPosition(),
"could not find module specified ");
}
BType functionToMockType = getFunctionType(packageEnvironmentMap, functionToMockID, vals[1]);
BType mockFunctionType = getFunctionType(packageEnvironmentMap, parent.packageID,
((BLangFunction) functionNode).name.toString());
if (functionToMockType != null && mockFunctionType != null) {
if (!typeChecker.isAssignable(mockFunctionType, functionToMockType)) {
diagnosticLog.logDiagnostic(Diagnostic.Kind.ERROR, ((BLangFunction) functionNode).pos,
"incompatible types: expected " + functionToMockType.toString()
+ " but found " + mockFunctionType.toString());
}
} else {
diagnosticLog.logDiagnostic(Diagnostic.Kind.ERROR, attachmentNode.getPosition(),
"could not find functions in module");
}
BLangTestablePackage bLangTestablePackage =
(BLangTestablePackage) ((BLangFunction) functionNode).parent;
bLangTestablePackage.addMockFunction(vals[0] + MOCK_ANNOTATION_DELIMITER + vals[1],
functionName);
}
} else if (TEST_ANNOTATION_NAME.equals(annotationName)) {
Test test = new Test();
test.setTestName(functionName);
AtomicBoolean shouldSkip = new AtomicBoolean();
AtomicBoolean groupsFound = new AtomicBoolean();
List<String> groups = registry.getGroups();
boolean shouldIncludeGroups = registry.shouldIncludeGroups();
if (attachmentNode.getExpression() instanceof BLangRecordLiteral) {
List<RecordLiteralNode.RecordField> attributes = ((BLangRecordLiteral) attachmentNode
.getExpression()).getFields();
attributes.forEach(field -> {
String name;
BLangExpression valueExpr;
if (field.isKeyValueField()) {
BLangRecordLiteral.BLangRecordKeyValueField attributeNode =
(BLangRecordLiteral.BLangRecordKeyValueField) field;
name = attributeNode.getKey().toString();
valueExpr = attributeNode.getValue();
} else {
BLangRecordLiteral.BLangRecordVarNameField varNameField =
(BLangRecordLiteral.BLangRecordVarNameField) field;
name = varNameField.variableName.value;
valueExpr = varNameField;
}
if (TEST_ENABLE_ANNOTATION_NAME.equals(name) && "false".equals(valueExpr
.toString())) {
shouldSkip.set(true);
return;
}
if (GROUP_ANNOTATION_NAME.equals(name)) {
if (valueExpr instanceof BLangListConstructorExpr) {
BLangListConstructorExpr values = (BLangListConstructorExpr) valueExpr;
test.setGroups(values.exprs.stream().map(node -> node.toString())
.collect(Collectors.toList()));
if (groups != null && !groups.isEmpty()) {
boolean isGroupPresent = isGroupAvailable(groups, test.getGroups());
if (shouldIncludeGroups) {
if (!isGroupPresent) {
shouldSkip.set(true);
return;
}
} else {
if (isGroupPresent) {
shouldSkip.set(true);
return;
}
}
groupsFound.set(true);
}
}
}
if (VALUE_SET_ANNOTATION_NAME.equals(name)) {
test.setDataProvider(valueExpr.toString());
}
if (BEFORE_FUNCTION.equals(name)) {
test.setBeforeTestFunction(valueExpr.toString());
}
if (AFTER_FUNCTION.equals(name)) {
test.setAfterTestFunction(valueExpr.toString());
}
if (DEPENDS_ON_FUNCTIONS.equals(name)) {
if (valueExpr instanceof BLangListConstructorExpr) {
BLangListConstructorExpr values = (BLangListConstructorExpr) valueExpr;
values.exprs.stream().map(node -> node.toString()).forEach
(test::addDependsOnTestFunction);
}
}
});
}
if (groups != null && !groups.isEmpty() && !groupsFound.get() && shouldIncludeGroups) {
shouldSkip.set(true);
}
if (!shouldSkip.get()) {
suite.addTests(test);
}
} else {
}
}
}