diff --git a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala index 59ea43cf6..cd769f424 100644 --- a/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala +++ b/compiler/lib/src/main/scala/analysis/ComputeDependencies/AddDependencies.scala @@ -142,40 +142,47 @@ object AddDependencies isAbsolute ).map(addDependencies (a)).getOrElse(Right(a)) - private def addDependenciesHelper(a: Analysis, specLoc: Ast.SpecLoc, file: File): Result = { - val dependencyFileSet = a.dependencyFileSet + file - val directDependencyFileSet = a.level match { - case 1 => a.directDependencyFileSet + file - case _ => a.directDependencyFileSet - } - val a1 = a.copy( - dependencyFileSet = dependencyFileSet, - directDependencyFileSet = directDependencyFileSet - ) + private def addDependenciesForFile(a: Analysis, file: File): Result = + val scopeNameList = a.scopeNameList val result = for { tu <- Parser.parseFile (Parser.transUnit) (None) (file) - pair <- ResolveSpecInclude.transUnit(a1, tu) - a2 <- ComputeDependencies.tuList( - pair._1.copy( + (a, tu) <- ResolveSpecInclude.transUnit(a, tu) + a <- ComputeDependencies.tuList( + a.copy( scopeNameList = Nil, - dependencyTuMap = pair._1.dependencyTuMap + (file -> pair._2) + dependencyTuMap = a.dependencyTuMap + (file -> tu) ), - List(pair._2) + List(tu) ) - } yield a2.copy(scopeNameList = a1.scopeNameList) + } yield a.copy(scopeNameList = scopeNameList) result match { case Left(FileError.CannotOpen(_, _)) => { - val a = a1.copy(missingDependencyFileSet = a1.missingDependencyFileSet + file) - Right(a) + val missingDependencyFileSet = a.missingDependencyFileSet + file + Right(a.copy(missingDependencyFileSet = missingDependencyFileSet)) } case _ => result } - } + + private def updateDirectDependencyFileSet(a: Analysis, file: File) = + val directDependencyFileSet = a.directDependencyFileSet + file + a.copy(directDependencyFileSet = directDependencyFileSet) + + private def updateDependencyFileSet(a: Analysis, file: File) = + val dependencyFileSet = a.dependencyFileSet + file + a.copy(dependencyFileSet = dependencyFileSet) private def addDependencies (a: Analysis) (specLoc: Ast.SpecLoc): Result = { val file = getFile(specLoc) - if !a.inputFileSet.contains(file) && !a.dependencyFileSet.contains(file) - then addDependenciesHelper(a, specLoc, file) + if !a.inputFileSet.contains(file) + then + val a1 = if a.level == 1 + then updateDirectDependencyFileSet(a, file) + else a + if !a1.dependencyFileSet.contains(file) + then + val a2 = updateDependencyFileSet(a1, file) + addDependenciesForFile(a2, file) + else Right(a1) else Right(a) } diff --git a/compiler/tools/fpp-depend/test/direct_already_seen.fpp b/compiler/tools/fpp-depend/test/direct_already_seen.fpp new file mode 100644 index 000000000..e4eebdff8 --- /dev/null +++ b/compiler/tools/fpp-depend/test/direct_already_seen.fpp @@ -0,0 +1,9 @@ +# Test direct dependencies already seen at a lower level +# The dependency on b exists in direct_already_seen_a.fpp at level 2 +# But it should be reported here as a direct dependency + +locate constant a at "direct_already_seen_a.fpp" +locate constant b at "direct_already_seen_b.fpp" + +constant c = a +constant d = b diff --git a/compiler/tools/fpp-depend/test/direct_already_seen.ref.txt b/compiler/tools/fpp-depend/test/direct_already_seen.ref.txt new file mode 100644 index 000000000..7bd3847e0 --- /dev/null +++ b/compiler/tools/fpp-depend/test/direct_already_seen.ref.txt @@ -0,0 +1,2 @@ +[ local path prefix ]/compiler/tools/fpp-depend/test/direct_already_seen_a.fpp +[ local path prefix ]/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp diff --git a/compiler/tools/fpp-depend/test/direct_already_seen_a.fpp b/compiler/tools/fpp-depend/test/direct_already_seen_a.fpp new file mode 100644 index 000000000..84b672789 --- /dev/null +++ b/compiler/tools/fpp-depend/test/direct_already_seen_a.fpp @@ -0,0 +1 @@ +constant a = b diff --git a/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp b/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp new file mode 100644 index 000000000..da1487112 --- /dev/null +++ b/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp @@ -0,0 +1 @@ +constant b = 0 diff --git a/compiler/tools/fpp-depend/test/direct_already_seen_output.ref.txt b/compiler/tools/fpp-depend/test/direct_already_seen_output.ref.txt new file mode 100644 index 000000000..7bd3847e0 --- /dev/null +++ b/compiler/tools/fpp-depend/test/direct_already_seen_output.ref.txt @@ -0,0 +1,2 @@ +[ local path prefix ]/compiler/tools/fpp-depend/test/direct_already_seen_a.fpp +[ local path prefix ]/compiler/tools/fpp-depend/test/direct_already_seen_b.fpp diff --git a/compiler/tools/fpp-depend/test/run b/compiler/tools/fpp-depend/test/run index 985105647..bd267f951 100755 --- a/compiler/tools/fpp-depend/test/run +++ b/compiler/tools/fpp-depend/test/run @@ -47,6 +47,15 @@ direct() test $run_test_status -eq 0 } +direct_already_seen() +{ + run_test '-d tmp.out.txt' direct_already_seen + run_test_status=$? + remove_path_prefix < tmp.out.txt > direct_already_seen_output.out.txt + compare direct_already_seen_output && \ + test $run_test_status -eq 0 +} + filenames() { run_test '-g filenames_generated_output.out.txt -u filenames_ut_output.out.txt' \ diff --git a/compiler/tools/fpp-depend/test/tests.sh b/compiler/tools/fpp-depend/test/tests.sh index bc08b1fbd..dec1d36d1 100644 --- a/compiler/tools/fpp-depend/test/tests.sh +++ b/compiler/tools/fpp-depend/test/tests.sh @@ -12,6 +12,7 @@ def_system dictionary dictionary_no_deployment_top direct +direct_already_seen enum_constant expr_array expr_binop diff --git a/compiler/tools/fpp-depend/test/update-ref b/compiler/tools/fpp-depend/test/update-ref index 4565616f1..db746d5cf 100755 --- a/compiler/tools/fpp-depend/test/update-ref +++ b/compiler/tools/fpp-depend/test/update-ref @@ -42,6 +42,11 @@ direct() { remove_path_prefix < tmp.out.txt > direct_output.ref.txt } +direct_already_seen() { + update '-d tmp.out.txt' direct_already_seen + remove_path_prefix < tmp.out.txt > direct_already_seen_output.ref.txt +} + filenames() { update '-g filenames_generated_output.ref.txt -u filenames_ut_output.ref.txt' \ ../../fpp-filenames/test/ok filenames diff --git a/docs/wiki/Computing-Dependencies.asciidoc b/docs/wiki/Computing-Dependencies.asciidoc index 3f8646b3f..2190d91d4 100644 --- a/docs/wiki/Computing-Dependencies.asciidoc +++ b/docs/wiki/Computing-Dependencies.asciidoc @@ -6,6 +6,7 @@ This algorithm computes dependencies for a list of translation units. _a_. The https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[input file set] of _a_ must record the set of files presented for analysis. +The level must be zero, and the scope name list must be empty. . A list _tul_ of FPP translation units. @@ -30,12 +31,14 @@ Run the <> on _tul_. To run the dependency algorithm on a translation unit list _tul_, do the following: +. *Increment the level:* Increment the level in _a_. + . *Resolve include specifiers:* Recursively resolve include specifiers in _tul_. Add the path of each included file to the included file set in _a_. If the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[level of _a_] -is zero, then add the path of each included file to the direct dependency +is one, then add the path of each included file to the direct dependency file set in _a_. . *Build the location specifier map:* Traverse each translation unit _tu_ in @@ -133,6 +136,8 @@ file set, if _f_ appears in the dependency file set, then delete it from the set. The dependency is already recorded in the file that includes _f_. +. *Decrement the level:* Decrement the level in _a_. + [[adding-dependencies]] === Adding Dependencies for a Location Specifier @@ -140,39 +145,38 @@ To add a dependency for a location specifier _s_, do the following: . Compute the absolute path _p_ associated with _s_. -. If _p_ is in the +. If _p_ is not in the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[input file set] -of _a_ or is already in the -https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[dependency file set] -of _a_, then do nothing. +of _a_, then -. Otherwise - -.. If the level of _a_ is zero, then add _p_ to the +.. If the level of _a_ is one, then add _p_ to the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[direct dependency file set] of _a_. -.. Add _p_ to the +.. If _p_ is not already in the +https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[dependency file set] +of _a_, then + +... Add _p_ to the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[dependency file set] of _a_. -.. If the file _f_ at _p_ exists, then +... If the file _f_ at _p_ exists, then -... Parse _f_, generating a translation unit _tu_. +.... Parse _f_, generating a translation unit _tu_. -... Recursively resolve include specifiers in _tu_. +.... Recursively resolve include specifiers in _tu_. Add the path of each included file to the included file set in _a_. -... Add the mapping from _p_ to _tu_ to the +.... Add the mapping from _p_ to _tu_ to the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[dependency translation unit map] of _a_. -... Run the <> on the list _[ tu ]_ +.... Run the <> on the list _[ tu ]_ with the value of _a_ computed so far, but with an empty scope name list. -Restore the current level and scope name list and -let the result be the new _a_. +Restore the current scope name list and let the result be the new _a_. -.. Otherwise add _p_ to the +... Otherwise add _p_ to the https://github.com/nasa/fpp/wiki/Analysis-Data-Structure[missing dependency file set] of _a_.