Skip to content

Commit

Permalink
extracted abstract occurrences method into ResolutionCtx
Browse files Browse the repository at this point in the history
  • Loading branch information
ghik committed Oct 17, 2019
1 parent 0448e68 commit e24007c
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 29 deletions.
7 changes: 2 additions & 5 deletions src/org/jetbrains/plugins/hocon/psi/HoconPsiElement.scala
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,7 @@ final class HObjectEntries(ast: ASTNode) extends HoconPsiElement(ast) with HEntr
def occurrences(path: List[String], opts: ResOpts, resCtx: ResolutionCtx): Iterator[ResolvedField] = path match {
case Nil => Iterator.empty
case firstKey :: restOfKeys =>
val occurrencesOfFirst = occurrences(Some(firstKey), opts, resCtx)
restOfKeys.foldLeft(occurrencesOfFirst) { (occ, key) =>
occ.flatMap(_.subOccurrences(Some(key), opts))
}
occurrences(Some(firstKey), opts, resCtx).flatMap(_.occurrences(restOfKeys, opts))
}

def makeContext: Option[ResolutionCtx] = parent match {
Expand Down Expand Up @@ -588,7 +585,7 @@ sealed trait HValue extends HoconPsiElement {
case conc: HConcatenation =>
conc.findChildren[HValue](opts.reverse).flatMap(_.occurrences(key, opts, resCtx))
case subst: HSubstitution =>
subst.resolve(opts, resCtx, backtrace = true).flatMap(_.subOccurrences(key, opts))
subst.resolve(opts, resCtx, backtrace = true).flatMap(_.occurrences(key, opts))
case _ =>
Iterator.empty
}
Expand Down
4 changes: 2 additions & 2 deletions src/org/jetbrains/plugins/hocon/ref/HKeyReference.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class HKeyReference(key: HKey) extends PsiReference {
case Some(prefixPath) =>
prefixPath.allKeys.flatMapIt { path =>
val strPath = path.map(_.stringValue)
toplevelCtx.occurrences(strPath, opts).flatMap(_.subOccurrences(None, opts))
toplevelCtx.occurrences(strPath, opts).flatMap(_.occurrences(None, opts))
}
case None =>
toplevelCtx.occurrences(None, opts)
Expand All @@ -54,7 +54,7 @@ class HKeyReference(key: HKey) extends PsiReference {
val prefixOccurrences =
if (entries.isToplevel) toplevelCtx.occurrences(strPath, opts)
else entries.occurrences(strPath, opts, toplevelCtx)
prefixOccurrences.flatMap(_.subOccurrences(None, opts))
prefixOccurrences.flatMap(_.occurrences(None, opts))
}
case None =>
if (entries.isToplevel) toplevelCtx.occurrences(None, opts)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class HoconPropertyReference(

val variantFields = fullPath.dropRight(reverseIndex + 1) match {
case Nil => toplevelCtx.occurrences(None, opts)
case prefixPath => toplevelCtx.occurrences(prefixPath, opts).flatMap(_.subOccurrences(None, opts))
case prefixPath => toplevelCtx.occurrences(prefixPath, opts).flatMap(_.occurrences(None, opts))
}
val seenKeys = new mutable.HashSet[String]
variantFields.filter(sf => seenKeys.add(sf.key)) // dirty, stateful filter
Expand Down
41 changes: 20 additions & 21 deletions src/org/jetbrains/plugins/hocon/semantics/ResolutionCtx.scala
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ sealed abstract class ResolutionCtx {
lazy val pathsInResolution: List[List[ResolvedField]] =
pathsInResolution(Nil, Nil)

def occurrences(subkey: Option[String], opts: ResOpts): Iterator[ResolvedField]

def occurrences(path: List[String], opts: ResOpts): Iterator[ResolvedField] = path match {
case Nil => Iterator(this).collectOnly[ResolvedField]
case head :: tail =>
val occurrencesOfFirst = occurrences(Some(head), opts)
tail.foldLeft(occurrencesOfFirst) {
case (occ, key) => occ.flatMap(_.occurrences(Some(key), opts))
}
}

/**
* Occurrences of given key (or all) adjacent to this resolution context (outside of it, before or after).
* Example: sibling fields of an `include`.
Expand All @@ -148,12 +159,12 @@ sealed abstract class ResolutionCtx {

case rf: ResolvedField => rf.subsCtx match {
case Some(sc) =>
rf.moreOccurrences(opts, withBacktraced = false).flatMap(_.subOccurrences(key, opts)) ++
rf.moreOccurrences(opts, withBacktraced = false).flatMap(_.occurrences(key, opts)) ++
sc.subst.adjacentConcatOccurrences(key, opts, sc.ctx) ++
sc.ctx.adjacentOccurrences(key, opts)

case None =>
rf.moreOccurrences(opts).flatMap(_.subOccurrences(key, opts))
rf.moreOccurrences(opts).flatMap(_.occurrences(key, opts))
}

case ic: IncludeCtx =>
Expand Down Expand Up @@ -203,15 +214,6 @@ case class ToplevelCtx(

def occurrences(subkey: Option[String], opts: ResOpts): Iterator[ResolvedField] =
toplevelIncludes(opts.reverse).flatMap(_.occurrences(subkey, opts))

def occurrences(path: List[String], opts: ResOpts): Iterator[ResolvedField] = path match {
case Nil => Iterator.empty
case head :: tail =>
val occurrencesOfFirst = occurrences(Some(head), opts)
tail.foldLeft(occurrencesOfFirst) {
case (occ, key) => occ.flatMap(_.subOccurrences(Some(key), opts))
}
}
}

object ToplevelCtx {
Expand Down Expand Up @@ -260,20 +262,15 @@ case class ResolvedField(
backtracedField.fold(this)(_.fullyBacktraced)

def firstSubOccurrence(subkey: Option[String], opts: ResOpts): Option[ResolvedField] =
subOccurrences(subkey, opts).nextOption
occurrences(subkey, opts).nextOption

def subOccurrences(subkey: Option[String], opts: ResOpts): Iterator[ResolvedField] = field match {
def occurrences(subkey: Option[String], opts: ResOpts): Iterator[ResolvedField] = field match {
case pf: HPrefixedField =>
pf.subField.occurrences(subkey, opts, this)
case vf: HValuedField =>
vf.subScopeValue.flatMapIt(_.occurrences(subkey, opts, this))
}

def subOccurrences(path: List[String], opts: ResOpts): Iterator[ResolvedField] =
path.foldLeft(Iterator(this)) {
case (it, key) => it.flatMap(_.subOccurrences(key.opt, opts))
}

val prefixField: Option[ResolvedField] = {
@tailrec def loop(parentCtx: ResolutionCtx): Option[ResolvedField] =
parentCtx match {
Expand Down Expand Up @@ -410,9 +407,9 @@ case class IncludeCtx(
) extends ResolutionCtx {
def file: HoconPsiFile = allFiles(fileIdx)

def occurrences(key: Option[String], opts: ResOpts): Iterator[ResolvedField] =
def occurrences(subkey: Option[String], opts: ResOpts): Iterator[ResolvedField] =
if (parentCtx.isAlreadyIn(file)) Iterator.empty
else file.toplevelEntries.flatMapIt(_.occurrences(key, opts, this))
else file.toplevelEntries.flatMapIt(_.occurrences(subkey, opts, this))

def firstOccurrence(key: Option[String], opts: ResOpts): Option[ResolvedField] =
occurrences(key, opts).nextOption
Expand All @@ -439,4 +436,6 @@ case class ArrayCtx(
parentCtx: ResolutionCtx,
arrayAppend: Boolean,
value: HValue, // either the array itself or element appended with +=
) extends ResolutionCtx
) extends ResolutionCtx {
def occurrences(subkey: Option[String], opts: ResOpts): Iterator[ResolvedField] = Iterator.empty
}

0 comments on commit e24007c

Please sign in to comment.