Index: tools/gn/substitution_pattern.cc |
diff --git a/tools/gn/substitution_pattern.cc b/tools/gn/substitution_pattern.cc |
index b589aaeaa400d11579cbcd92dd9c0f8d3efe5b4e..6a4d0c59158130f174d4d468290f4f0384ff9219 100644 |
--- a/tools/gn/substitution_pattern.cc |
+++ b/tools/gn/substitution_pattern.cc |
@@ -5,7 +5,9 @@ |
#include "tools/gn/substitution_pattern.h" |
#include "base/strings/string_number_conversions.h" |
+#include "tools/gn/build_settings.h" |
#include "tools/gn/err.h" |
+#include "tools/gn/filesystem_utils.h" |
#include "tools/gn/value.h" |
SubstitutionPattern::Subrange::Subrange() |
@@ -21,7 +23,7 @@ SubstitutionPattern::Subrange::Subrange(SubstitutionType t, |
SubstitutionPattern::Subrange::~Subrange() { |
} |
-SubstitutionPattern::SubstitutionPattern() { |
+SubstitutionPattern::SubstitutionPattern() : origin_(NULL) { |
} |
SubstitutionPattern::~SubstitutionPattern() { |
@@ -80,14 +82,12 @@ bool SubstitutionPattern::Parse(const std::string& str, |
} |
} |
- // Fill required types vector. |
- bool required_type_bits[SUBSTITUTION_NUM_TYPES] = {0}; |
- FillRequiredTypes(required_type_bits); |
+ origin_ = origin; |
- for (size_t i = SUBSTITUTION_FIRST_PATTERN; i < SUBSTITUTION_NUM_TYPES; i++) { |
- if (required_type_bits[i]) |
- required_types_.push_back(static_cast<SubstitutionType>(i)); |
- } |
+ // Fill required types vector. |
+ SubstitutionBits bits; |
+ FillRequiredTypes(&bits); |
+ bits.FillVector(&required_types_); |
return true; |
} |
@@ -102,10 +102,38 @@ std::string SubstitutionPattern::AsString() const { |
return result; |
} |
-void SubstitutionPattern::FillRequiredTypes( |
- bool required_types[SUBSTITUTION_NUM_TYPES]) const { |
+void SubstitutionPattern::FillRequiredTypes(SubstitutionBits* bits) const { |
for (size_t i = 0; i < ranges_.size(); i++) { |
if (ranges_[i].type != SUBSTITUTION_LITERAL) |
- required_types[static_cast<size_t>(ranges_[i].type)] = true; |
+ bits->used[static_cast<size_t>(ranges_[i].type)] = true; |
+ } |
+} |
+ |
+bool SubstitutionPattern::IsInOutputDir(const BuildSettings* build_settings, |
+ Err* err) const { |
+ if (ranges_.empty()) { |
+ *err = Err(origin_, "This is empty but I was expecting an output file."); |
+ return false; |
} |
+ |
+ if (ranges_[0].type == SUBSTITUTION_LITERAL) { |
+ // If the first thing is a literal, it must start with the output dir. |
+ if (!EnsureStringIsInOutputDir( |
+ build_settings->build_dir(), |
+ ranges_[0].literal, origin_, err)) |
+ return false; |
+ } else { |
+ // Otherwise, the first subrange must be a pattern that expands to |
+ // something in the output directory. |
+ if (!SubstitutionIsInOutputDir(ranges_[0].type)) { |
+ *err = Err(origin_, |
+ "File is not inside output directory.", |
+ "The given file should be in the output directory. Normally you\n" |
+ "would specify\n\"$target_out_dir/foo\" or " |
+ "\"{{source_gen_dir}}/foo\"."); |
+ return false; |
+ } |
+ } |
+ |
+ return true; |
} |