Skip to content
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

Fix duplicate issues on provider usage #260

Merged
merged 3 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions jvm/src/main/scala/com/nawforce/apexlink/cst/CST.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package com.nawforce.apexlink.cst

import com.nawforce.apexlink.diagnostics.IssueOps
import com.nawforce.apexlink.names.XNames.NameUtils
import com.nawforce.apexlink.org.OrgInfo
import com.nawforce.apexparser.ApexParser._
import com.nawforce.pkgforce.names.{Name, Names, TypeName}
import com.nawforce.pkgforce.path.Positionable
Expand Down Expand Up @@ -44,13 +43,13 @@ object CST {
}

final case class Id(name: Name) extends CST {
def validate(): Unit = {
def validate(context: VerifyContext): Unit = {
if (name.nonEmpty) {
val illegalError = name.isLegalIdentifier
if (illegalError.nonEmpty)
OrgInfo.log(IssueOps.illegalIdentifier(location, name, illegalError.get))
context.log(IssueOps.illegalIdentifier(location, name, illegalError.get))
else if (name.isReservedIdentifier)
OrgInfo.log(IssueOps.reservedIdentifier(location, name))
context.log(IssueOps.reservedIdentifier(location, name))
}
}
}
Expand Down
35 changes: 15 additions & 20 deletions jvm/src/main/scala/com/nawforce/apexlink/cst/Creator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,9 @@

package com.nawforce.apexlink.cst

import com.nawforce.apexlink.cst.AssignableSupport.{
AssignableOptions,
couldBeEqual,
isAssignableDeclaration
}
import com.nawforce.apexlink.cst.AssignableSupport.{couldBeEqual, isAssignableDeclaration}
import com.nawforce.apexlink.names.TypeNames
import com.nawforce.apexlink.names.TypeNames._
import com.nawforce.apexlink.org.OrgInfo
import com.nawforce.apexlink.types.core.TypeDeclaration
import com.nawforce.apexparser.ApexParser._
import com.nawforce.pkgforce.modifiers.ABSTRACT_MODIFIER
Expand Down Expand Up @@ -179,12 +174,12 @@ final case class ClassCreatorRest(arguments: ArraySeq[Expression]) extends Creat
input match {
case Some(td) =>
if (td.modifiers.contains(ABSTRACT_MODIFIER)) {
OrgInfo.logError(location, s"Abstract classes cannot be constructed: ${td.typeName}")
context.logError(location, s"Abstract classes cannot be constructed: ${td.typeName}")
return ExprContext.empty
}
td.findConstructor(arguments, context) match {
case Left(error) =>
OrgInfo.logError(location, error)
context.logError(location, error)
ExprContext.empty
case Right(ctor) => ExprContext(Some(false), input, ctor)
}
Expand All @@ -204,7 +199,7 @@ final case class ClassCreatorRest(arguments: ArraySeq[Expression]) extends Creat
rhs.verify(input, context)
Some(id)
case argument =>
OrgInfo.logError(
context.logError(
argument.location,
s"SObject type '$typeName' construction needs '<field name> = <value>' arguments"
)
Expand All @@ -214,7 +209,7 @@ final case class ClassCreatorRest(arguments: ArraySeq[Expression]) extends Creat
if (validArgs.length == arguments.length) {
val duplicates = validArgs.groupBy(_.name).collect { case (_, ArraySeq(_, y, _*)) => y }
if (duplicates.nonEmpty) {
OrgInfo.logError(
context.logError(
duplicates.head.location,
s"Duplicate assignment to field '${duplicates.head.name}' on SObject type '$typeName'"
)
Expand Down Expand Up @@ -259,7 +254,7 @@ final case class ArrayCreatorRest(
val indexType = expr.verify(input, context)
indexType.declaration.foreach(indexType => {
if (indexType.typeName != TypeNames.Integer) {
OrgInfo.logError(
context.logError(
expr.location,
s"Index for array construction must be an Integer, not '${indexType.typeName}'"
)
Expand All @@ -272,7 +267,7 @@ final case class ArrayCreatorRest(
val exprType = expr.verify(input, context)
exprType.declaration.foreach(exprType => {
if (!isAssignableDeclaration(creating.typeName, exprType, context)) {
OrgInfo.logError(
context.logError(
expr.location,
s"Expression of type '${exprType.typeName}' can not be assigned to ${creating.typeName}'"
)
Expand Down Expand Up @@ -323,7 +318,7 @@ final case class MapCreatorRest(pairs: List[MapCreatorRestPair]) extends Creator
val enclosedTypes = td.typeName.getMapType

if (enclosedTypes.isEmpty) {
OrgInfo.logError(
context.logError(
location,
s"Expression pair list construction is only supported for Map types, not '${td.typeName}'"
)
Expand All @@ -333,14 +328,14 @@ final case class MapCreatorRest(pairs: List[MapCreatorRestPair]) extends Creator
val keyType = context.getTypeAndAddDependency(enclosedTypes.get._1, context.thisType)
if (keyType.isLeft) {
if (!context.module.isGhostedType(enclosedTypes.get._1))
OrgInfo.log(keyType.swap.getOrElse(throw new NoSuchElementException).asIssue(location))
context.log(keyType.swap.getOrElse(throw new NoSuchElementException).asIssue(location))
return ExprContext.empty
}

val valueType = context.getTypeAndAddDependency(enclosedTypes.get._2, context.thisType)
if (valueType.isLeft) {
if (!context.module.isGhostedType(enclosedTypes.get._2))
OrgInfo.log(valueType.swap.getOrElse(throw new NoSuchElementException).asIssue(location))
context.log(valueType.swap.getOrElse(throw new NoSuchElementException).asIssue(location))
return ExprContext.empty
}

Expand All @@ -350,7 +345,7 @@ final case class MapCreatorRest(pairs: List[MapCreatorRestPair]) extends Creator
val isKeyAssignable =
couldBeEqual(pairContext._1.typeDeclaration, keyType.toOption.get, context)
if (!isKeyAssignable) {
OrgInfo.logError(
context.logError(
location,
s"Incompatible key type '${pairContext._1.typeName}' for '${keyType.toOption.get.typeName}'"
)
Expand All @@ -361,7 +356,7 @@ final case class MapCreatorRest(pairs: List[MapCreatorRestPair]) extends Creator
val isValueAssignable =
couldBeEqual(pairContext._2.typeDeclaration, valueType.toOption.get, context)
if (!isValueAssignable) {
OrgInfo.logError(
context.logError(
location,
s"Incompatible value type '${pairContext._2.typeName}' for '${valueType.toOption.get.typeName}'"
)
Expand Down Expand Up @@ -428,7 +423,7 @@ final case class SetOrListCreatorRest(parts: ArraySeq[Expression]) extends Creat
val td = creating.declaration.get
val enclosedType = td.typeName.getSetOrListType
if (enclosedType.isEmpty) {
OrgInfo.logError(
context.logError(
location,
s"Expression list construction is only supported for Set or List types, not '${td.typeName}'"
)
Expand All @@ -439,15 +434,15 @@ final case class SetOrListCreatorRest(parts: ArraySeq[Expression]) extends Creat
context.getTypeAndAddDependency(enclosedType.get, context.thisType) match {
case Left(error) =>
if (!context.module.isGhostedType(enclosedType.get))
OrgInfo.log(error.asIssue(location))
context.log(error.asIssue(location))
ExprContext.empty
case Right(toType) =>
// For each expression check we can assign to the generic type
parts.foreach(part => {
val exprType = part.verify(input, context)
exprType.declaration.foreach(exprType => {
if (!isAssignableDeclaration(toType.typeName, exprType, context)) {
OrgInfo.logError(
context.logError(
location,
s"Expression of type '${exprType.typeName}' can not be assigned to ${toType.typeName}'"
)
Expand Down
16 changes: 8 additions & 8 deletions jvm/src/main/scala/com/nawforce/apexlink/cst/Expressions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import com.nawforce.apexlink.diagnostics.IssueOps
import com.nawforce.apexlink.finding.TypeResolver
import com.nawforce.apexlink.names.TypeNames
import com.nawforce.apexlink.names.TypeNames._
import com.nawforce.apexlink.org.{OPM, OrgInfo, Referenceable}
import com.nawforce.apexlink.org.{OPM, Referenceable}
import com.nawforce.apexlink.types.apex.{ApexClassDeclaration, ApexConstructorLike}
import com.nawforce.apexlink.types.core.{FieldDeclaration, MethodDeclaration, TypeDeclaration}
import com.nawforce.apexlink.types.other.{AnyDeclaration, RecordSetDeclaration}
Expand Down Expand Up @@ -755,7 +755,7 @@ final case class PostfixExpression(expression: Expression, op: String) extends E
if inter.isStatic.contains(false) =>
inter
case _ =>
OrgInfo.logError(
context.logError(
location,
s"Postfix increment/decrement is not supported on type '${td.typeName}'"
)
Expand All @@ -781,7 +781,7 @@ final case class PrefixExpression(expression: Expression, op: String) extends Ex
case _ if inter.isStatic.contains(false) && op == "+" =>
ExprContext(isStatic = Some(false), PlatformTypes.stringType)
case _ =>
OrgInfo.logError(location, s"Prefix operations are not supported on type '${td.typeName}'")
context.logError(location, s"Prefix operations are not supported on type '${td.typeName}'")
ExprContext.empty
}
}
Expand All @@ -799,7 +799,7 @@ final case class NegationExpression(expression: Expression, isBitwise: Boolean)
case TypeNames.Integer if isBitwise && inter.isStatic.contains(false) => inter
case TypeNames.Long if isBitwise && inter.isStatic.contains(false) => inter
case _ =>
OrgInfo.logError(location, s"Negation operations is not supported on type '${td.typeName}'")
context.logError(location, s"Negation operations is not supported on type '${td.typeName}'")
ExprContext.empty
}
}
Expand Down Expand Up @@ -851,13 +851,13 @@ final case class BinaryExpression(lhs: Expression, rhs: Expression, op: String)
return ExprContext.empty

if (leftInter.isStatic.contains(true))
OrgInfo.logError(
context.logError(
location,
s"Expecting instance for operation, not type '${leftInter.typeName}'"
)

if (rightInter.isStatic.contains(true))
OrgInfo.logError(
context.logError(
location,
s"Expecting instance for operation, not type '${rightInter.typeName}'"
)
Expand All @@ -874,7 +874,7 @@ final case class BinaryExpression(lhs: Expression, rhs: Expression, op: String)

operation.verify(leftInter, rightInter, op, context) match {
case Left(error) =>
OrgInfo.logError(location, error)
context.logError(location, error)
ExprContext.empty
case Right(context) => context
}
Expand Down Expand Up @@ -904,7 +904,7 @@ final case class QueryExpression(query: Expression, lhs: Expression, rhs: Expres

ConditionalOperation.verify(leftInter, rightInter, "?", context) match {
case Left(error) =>
OrgInfo.logError(location, error)
context.logError(location, error)
ExprContext.empty
case Right(context) => context
}
Expand Down
13 changes: 7 additions & 6 deletions jvm/src/main/scala/com/nawforce/apexlink/cst/Statements.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import com.nawforce.apexlink.cst.AssignableSupport.isAssignableDeclaration
import com.nawforce.apexlink.cst.stmts._
import com.nawforce.apexlink.names.TypeNames
import com.nawforce.apexlink.names.TypeNames.TypeNameUtils
import com.nawforce.apexlink.org.OrgInfo
import com.nawforce.apexlink.types.core.TypeDeclaration
import com.nawforce.apexparser.ApexParser._
import com.nawforce.pkgforce.diagnostics.{ERROR_CATEGORY, Issue, LoggerOps}
Expand All @@ -45,7 +44,7 @@ abstract class Statement extends CST with ControlFlow {
* need to use.
*/
abstract class Block extends Statement {
def statements(): Seq[Statement]
def statements(context: Option[BlockVerifyContext] = None): Seq[Statement]
}

object Block {
Expand Down Expand Up @@ -110,12 +109,12 @@ private final case class OuterBlock(

override def verify(context: BlockVerifyContext): Unit = {
val blockContext = new InnerBlockVerifyContext(context)
statements().foreach(_.verify(blockContext))
statements(Some(blockContext)).foreach(_.verify(blockContext))
verifyControlPath(blockContext, BlockControlPattern())
context.typePlugin.foreach(_.onBlockValidated(this, context.isStatic, blockContext))
}

override def statements(): Seq[Statement] = {
override def statements(context: Option[BlockVerifyContext] = None): Seq[Statement] = {
var statements = Option(statementsRef).map(_.get).orNull

// If the statement WeakRef has gone stale we need to re-build them
Expand All @@ -125,7 +124,7 @@ private final case class OuterBlock(
if (statementContext == null) {
val parser = new CodeParser(source)
val result = parser.parseBlock()
result.issues.foreach(OrgInfo.log)
context.foreach(c => result.issues.foreach(c.log))
statementContext = result.value
blockContextRef = new WeakReference(statementContext)
reParsed = true
Expand Down Expand Up @@ -164,6 +163,8 @@ private final case class InnerBlock(statements: Seq[Statement]) extends Block {
statements.foreach(_.verify(blockContext))
verifyControlPath(blockContext, BlockControlPattern())
}

override def statements(context: Option[BlockVerifyContext] = None): Seq[Statement] = statements
}

final case class LocalVariableDeclarationStatement(
Expand Down Expand Up @@ -280,7 +281,7 @@ final case class EnhancedForControl(typeName: TypeName, id: Id, expression: Expr
}

override def verify(context: BlockVerifyContext): Unit = {
id.validate()
id.validate(context)

// Check the loop var type is available
var varTd = context.getTypeAndAddDependency(typeName, context.thisType).toOption
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ final case class VariableDeclarator(
init: Option[Expression]
) extends CST {
def verify(input: ExprContext, context: BlockVerifyContext): Unit = {
id.validate()
id.validate(context)

val lhsType = context.getTypeAndAddDependency(typeName, context.thisType).toOption

Expand Down
Loading