Refactor ICG to report skipped files consistently

Refs #394
This commit is contained in:
Derek Bankieris 2017-03-15 15:53:56 -05:00
parent b88c75631a
commit 73cbbd96cd
9 changed files with 195 additions and 163 deletions

View File

@ -145,15 +145,12 @@ sub make_swig_makefile() {
$swig_src_dir = "build" ;
foreach $n (@files_to_process) {
# check to see if the parent directory of each file is writable.
# If it isn't, then don't add it to the list of files to requiring ICG
$f = abs_path(dirname($n)) . "/" . basename($n) ;
my ($continue) = 1 ;
foreach my $ie ( @swig_exclude_dirs ) {
# if file location begins with $ie (an IGC exclude dir)
# if file location begins with $ie (a SWIG exclude dir)
if ( $f =~ /^\Q$ie/ ) {
print "CP(swig) skipping $f (ICG exclude dir $ie)\n" ;
print "CP(swig) skipping $f (SWIG exclude dir $ie)\n" ;
$continue = 0 ;
last ; # break out of loop
}

View File

@ -152,11 +152,9 @@ bool CXXRecordVisitor::VisitCXXRecordDecl( clang::CXXRecordDecl *rec ) {
// Return false to stop processing if this header file is excluded by one of many reasons.
std::string header_file_name = getFileName(ci , rec->RBRACELOC(), hsd) ;
char * rp = almostRealPath(header_file_name.c_str()) ;
if ( rp == NULL ||
!hsd.isPathInUserDir(rp) ||
hsd.isPathInExclude(rp) ||
hsd.isPathInICGExclude(rp) ||
cs.hasICGNo(header_file_name) ) {
if ( rp == NULL || pa.isHeaderExcluded(header_file_name) ) {
// mark the header as visited so PrintAttributes doesn't process it during addEmptyFiles()
pa.markHeaderAsVisited(header_file_name);
return false ;
}
cval.setCompat15(hsd.isPathInCompat15(rp)) ;

View File

@ -221,7 +221,7 @@ std::set< std::string > CommentSaver::getIgnoreTypes( std::string file_name ) {
start = th_str.find( "trick_exclude_typename", start ) ;
}
std::transform(th_str.begin(), th_str.end(), th_str.begin(), ::toupper) ;
//std::transform(th_str.begin(), th_str.end(), th_str.begin(), ::toupper) ;
memset(pmatch , 0 , sizeof(pmatch)) ;

View File

@ -166,6 +166,10 @@ std::string ConstructValues::getFullyQualifiedName(const std::string& delimiter)
return oss.str();
}
bool ConstructValues::isNameOrFileNameEmpty() {
return name.empty() or file_name.empty();
}
void ConstructValues::printOpenNamespaceBlocks(std::ostream& ostream) {
for (auto name : namespaces) {
ostream << "namespace " << name << " {" << std::endl;

View File

@ -67,8 +67,10 @@ class ConstructValues {
void printNamespaces(std::ostream& ostream, const std::string& delimiter = "::") ;
void printContainerClasses(std::ostream& ostream, const std::string& delimiter = "::") ;
void printNamespacesAndContainerClasses(std::ostream& ostream, const std::string& delimiter = "::") ;
std::string getNamespacesAndContainerClasses(const std::string& delimiter = "::") ;
std::string getFullyQualifiedTypeName(const std::string& delimiter = "::") ;
bool isNameOrFileNameEmpty();
protected:

View File

@ -18,7 +18,6 @@
#include "CommentSaver.hh"
#include "ClassValues.hh"
#include "EnumValues.hh"
#include "Utilities.hh"
PrintAttributes::PrintAttributes(int in_attr_version , HeaderSearchDirs & in_hsd ,
CommentSaver & in_cs , clang::CompilerInstance & in_ci, bool in_force , bool in_sim_services_flag ,
@ -130,65 +129,14 @@ bool PrintAttributes::openIOFile(const std::string& header_file_name) {
return false;
}
// add it to the list of visited files
visited_files.insert(header_file_name) ;
// several tests require the real path of the header file
char* temp = almostRealPath(header_file_name.c_str());
if (!temp) {
std::cout << bold(color(WARNING, "Warning")) << " ICG could not resolve realpath of " << quote(bold(header_file_name)) << std::endl;
return false;
}
const std::string realPath = std::string(temp);
const bool verboseBuild = getenv("TRICK_VERBOSE_BUILD");
/**
* Exclude files:
* - in system directories
* - in TRICK_EXCLUDE directories
* - in TRICK_ICG_EXCLUDE directories
* - in TRICK_EXT_LIB_DIRS directories
* - whose Trick header comments preclude ICG
*/
const std::string skipping = color(INFO, "Skipping ");
if (!hsd.isPathInUserDir(realPath)) {
return false;
}
if (hsd.isPathInExclude(realPath)) {
if (verboseBuild) {
std::cout << skipping << "TRICK_EXCLUDE: " << underline(realPath, hsd.getPathInExclude(realPath).size()) << std::endl;
}
return false;
}
if (hsd.isPathInICGExclude(realPath)) {
if (verboseBuild) {
std::cout << skipping << "TRICK_ICG_EXCLUDE: " << underline(realPath, hsd.getPathInICGExclude(realPath).size()) << std::endl;
}
return false;
}
if (hsd.isPathInExtLib(realPath)) {
if (verboseBuild) {
std::cout << skipping << "TRICK_EXT_LIB_DIRS: " << underline(realPath, hsd.getPathInExtLib(realPath).size()) << std::endl;
}
ext_lib_io_files.insert(header_file_name) ;
return false;
}
if (cs.hasICGNo(header_file_name)) {
if (verboseBuild) {
std::cout << skipping << "ICG: (NO): " << realPath << std::endl;
}
icg_no_files.push_back(realPath);
if (isHeaderExcluded(header_file_name)) {
return false;
}
// map the header to its IO file
char* realPath = almostRealPath(header_file_name.c_str());
const std::string io_file_name = createIOFileName(realPath) ;
all_io_files[header_file_name] = io_file_name ;
@ -199,8 +147,10 @@ bool PrintAttributes::openIOFile(const std::string& header_file_name) {
// no further processing is required if it's not out of date
if (!isIOFileOutOfDate(realPath, io_file_name)) {
free(realPath);
return false;
}
free(realPath);
// add it to the map of out of date IO files
out_of_date_io_files[header_file_name] = io_file_name ;
@ -214,9 +164,6 @@ bool PrintAttributes::openIOFile(const std::string& header_file_name) {
<< " No Trick header comment found" << std::endl;
}
// get the ignored types from this header
ignored_types[header_file_name] = cs.getIgnoreTypes(header_file_name) ;
return true ;
}
@ -273,66 +220,59 @@ std::string PrintAttributes::createIOFileName(std::string header_file_name) {
}
void PrintAttributes::printClass( ClassValues * cv ) {
// If the class name is not empty and the filename is not empty
if ( (! cv->getName().empty()) and !cv->getFileName().empty() ) {
// If we have not processed this class before
if ( processed_classes[cv->getFileName()].find(cv->getFullyQualifiedMangledTypeName()) ==
processed_classes[cv->getFileName()].end() ) {
// mark the class as processed.
processed_classes[cv->getFileName()].insert(cv->getFullyQualifiedMangledTypeName()) ;
// If the class name is not specified as ignored in Trick header ICG_IGNORE field.
if ( ignored_types[cv->getFileName()].find(cv->getName()) == ignored_types[cv->getFileName()].end() and
ignored_types[cv->getFileName()].find(cv->getFullyQualifiedName()) == ignored_types[cv->getFileName()].end() ) {
// if we are successful in opening the io_src file
if ( openIOFile( cv->getFileName()) ) {
// print the attributes
printer->printClass(outfile, cv) ;
// close the io_src file
outfile.close() ;
}
ClassValues& classValues = *cv;
// if we are successful in opening the map file
char * realPath = almostRealPath(cv->getFileName().c_str()) ;
if ( realPath != NULL ) {
if ( isFileIncluded( cv->getFileName()) or hsd.isPathInExtLib(realPath)) {
printer->printClassMap(class_map_outfile, cv) ;
}
free(realPath) ;
}
}
if (classValues.isNameOrFileNameEmpty()) {
return;
}
if (hasBeenProcessed(classValues)) {
return;
}
if (isIgnored(classValues)) {
return;
}
const std::string& fileName = classValues.getFileName();
if (openIOFile(fileName)) {
printer->printClass(outfile, cv);
outfile.close();
}
char* realPath = almostRealPath(fileName.c_str());
if (realPath) {
if (isFileIncluded(fileName) or hsd.isPathInExtLib(realPath)) {
printer->printClassMap(class_map_outfile, cv);
}
free(realPath);
}
}
void PrintAttributes::printEnum( EnumValues * ev ) {
// If the enum name is not empty and the filename is not empty
if ( (! ev->getName().empty()) and !ev->getFileName().empty() ) {
// If we have not processed this enum before
if ( processed_enums[ev->getFileName()].find(ev->getFullyQualifiedName()) == processed_enums[ev->getFileName()].end() ) {
// mark the enum as processed.
processed_enums[ev->getFileName()].insert(ev->getFullyQualifiedName()) ;
// If the enum name is not specified as ignored in Trick header ICG_IGNORE field.
if ( ignored_types[ev->getFileName()].find(ev->getName()) == ignored_types[ev->getFileName()].end() and
ignored_types[ev->getFileName()].find(ev->getFullyQualifiedName()) == ignored_types[ev->getFileName()].end()) {
// if we are successful in opening the io_src file
if ( openIOFile( ev->getFileName()) ) {
// print the attributes and close the io_src file
printer->printEnum(outfile, ev) ;
outfile.close() ;
}
void PrintAttributes::printEnum(EnumValues* ev) {
EnumValues& enumValues = *ev;
// if we are successful in opening the map file
if ( isFileIncluded( ev->getFileName())) {
printer->printEnumMap(enum_map_outfile, ev) ;
}
}
}
if (enumValues.isNameOrFileNameEmpty()) {
return;
}
}
void PrintAttributes::removeMapFiles() {
//remove("io_src/class_map.cpp") ;
//remove("io_src/enum_map.cpp") ;
if (hasBeenProcessed(enumValues)) {
return;
}
if (isIgnored(enumValues)) {
return;
}
const std::string& fileName = enumValues.getFileName();
if (openIOFile(fileName)) {
printer->printEnum(outfile, ev) ;
outfile.close() ;
}
if (isFileIncluded(fileName)) {
printer->printEnumMap(enum_map_outfile, ev) ;
}
}
void PrintAttributes::createMapFiles() {
@ -383,40 +323,29 @@ void PrintAttributes::closeMapFiles() {
}
}
void PrintAttributes::addEmptyFiles() {
// Make a list of the empty files we processed.
// This list is written to the ICG_processed file and used by other processors.
clang::SourceManager::fileinfo_iterator fi ;
for ( fi = ci.getSourceManager().fileinfo_begin() ; fi != ci.getSourceManager().fileinfo_end() ; fi++ ) {
// Make a list of the empty files we processed.
// This list is written to the ICG_processed file and used by other processors.
std::set<std::string> PrintAttributes::getEmptyFiles() {
std::set<std::string> emptyFiles;
for (auto fi = ci.getSourceManager().fileinfo_begin() ; fi != ci.getSourceManager().fileinfo_end() ; ++fi ) {
const clang::FileEntry * fe = (*fi).first ;
std::string header_file_name = fe->getName() ;
if ( visited_files.find(header_file_name) == visited_files.end() ) {
visited_files.insert(header_file_name) ;
// several tests require the real path of the header file.
char * realPath = almostRealPath(header_file_name.c_str()) ;
if ( realPath != NULL ) {
// Only include user directories (not system dirs like /usr/include)
if ( hsd.isPathInUserDir(realPath) ) {
if ( hsd.isPathInExclude(realPath) == false ) {
if ( hsd.isPathInICGExclude(realPath) == false ) {
// Only include files that do not have ICG: (No)
// hasICGNo uses original header name, not the real path
if ( ! cs.hasICGNo(header_file_name) ) {
// Don't process files in excluded directories
if ( hsd.isPathInExtLib(realPath) == false ) {
std::string io_file_name = createIOFileName(std::string(realPath)) ;
empty_header_files.insert(realPath) ;
} else {
ext_lib_io_files.insert(realPath) ;
}
}
}
}
}
free(realPath) ;
}
if ( visited_files.find(header_file_name) != visited_files.end() ) {
continue;
}
visited_files.insert(header_file_name) ;
if (isHeaderExcluded(header_file_name)) {
continue;
}
char* path = almostRealPath(header_file_name.c_str());
emptyFiles.insert(path);
free(path) ;
}
return emptyFiles;
}
//TODO: Move this into PrintFileContents10.
@ -491,10 +420,8 @@ void PrintAttributes::printIOMakefile() {
makefile_ICG.close() ;
// Create the list of empty (of classes/enums) header files to be written to ICG_processed.
addEmptyFiles() ;
std::set< std::string >::iterator sit ;
for ( sit = empty_header_files.begin() ; sit != empty_header_files.end() ; sit++ ) {
ICG_processed << (*sit) << std::endl ;
for ( auto& file : getEmptyFiles() ) {
ICG_processed << file << std::endl ;
}
ICG_processed.close() ;
@ -502,8 +429,8 @@ void PrintAttributes::printIOMakefile() {
io_link_list.close() ;
ext_lib.open("build/ICG_ext_lib") ;
for ( sit = ext_lib_io_files.begin() ; sit != ext_lib_io_files.end() ; sit++ ) {
ext_lib << (*sit) << std::endl ;
for ( auto& file : ext_lib_io_files ) {
ext_lib << file << std::endl ;
}
ext_lib.close() ;
}
@ -518,3 +445,94 @@ void PrintAttributes::printICGNoFiles() {
icg_no_outfile.close() ;
}
}
bool PrintAttributes::hasBeenProcessed(EnumValues& enumValues) {
return hasBeenProcessed(enumValues.getFullyQualifiedName(), processed_enums[enumValues.getFileName()]);
}
bool PrintAttributes::hasBeenProcessed(ClassValues& classValues) {
return hasBeenProcessed(classValues.getFullyQualifiedMangledTypeName(), processed_classes[classValues.getFileName()]);
}
bool PrintAttributes::hasBeenProcessed(const std::string& name, std::set<std::string>& processedSet) {
bool processed = processedSet.find(name) != processedSet.end();
if (!processed) {
processedSet.insert(name);
}
return processed;
}
bool PrintAttributes::isIgnored(ConstructValues& constructValues) {
const std::string& fileName = constructValues.getFileName();
if (ignored_types.find(fileName) == ignored_types.end()) {
ignored_types[fileName] = cs.getIgnoreTypes(fileName) ;
}
std::set<std::string>& constructs = ignored_types[fileName];
const bool ignored = constructs.find(constructValues.getName()) != constructs.end() or
constructs.find(constructValues.getFullyQualifiedName()) != constructs.end();
if (ignored and verboseBuild) {
std::cout << skipping << "ICG Ignore Type: " << constructValues.getName() << " (from " << fileName << ")" << std::endl;
}
return ignored;
}
bool PrintAttributes::isHeaderExcluded(const std::string& header) {
char* temp = almostRealPath(header.c_str());
if (!temp) {
return true;
}
const std::string path = std::string(temp);
free(temp);
/**
* Exclude files:
* - in system directories
* - in TRICK_EXCLUDE directories
* - in TRICK_ICG_EXCLUDE directories
* - in TRICK_EXT_LIB_DIRS directories
* - whose Trick header comments preclude ICG
*/
if (!hsd.isPathInUserDir(path)) {
return true;
}
if (hsd.isPathInExclude(path)) {
if (verboseBuild) {
std::cout << skipping << "TRICK_EXCLUDE: " << underline(path, hsd.getPathInExclude(path).size()) << std::endl;
}
return true;
}
if (hsd.isPathInICGExclude(path)) {
if (verboseBuild) {
std::cout << skipping << "TRICK_ICG_EXCLUDE: " << underline(path, hsd.getPathInICGExclude(path).size()) << std::endl;
}
return true;
}
if (hsd.isPathInExtLib(path)) {
if (verboseBuild) {
std::cout << skipping << "TRICK_EXT_LIB_DIRS: " << underline(path, hsd.getPathInExtLib(path).size()) << std::endl;
}
ext_lib_io_files.insert(header) ;
return true;
}
if (cs.hasICGNo(header)) {
if (verboseBuild) {
std::cout << skipping << "ICG: (NO): " << path << std::endl;
}
icg_no_files.push_back(path);
return true;
}
return false;
}
void PrintAttributes::markHeaderAsVisited(const std::string& header) {
visited_files.insert(header);
}

View File

@ -8,11 +8,13 @@
#include <vector>
#include <map>
#include <set>
#include "Utilities.hh"
namespace clang {
class CompilerInstance ;
}
class ConstructValues ;
class ClassValues ;
class EnumValues ;
class PrintFileContentsBase ;
@ -38,7 +40,6 @@ class PrintAttributes {
clang::CompilerInstance & in_ci, bool force , bool sim_services, std::string output_dir ) ;
/** Prints all of the processed classes and enumerations */
virtual void removeMapFiles() ;
virtual void createMapFiles() ;
virtual void closeMapFiles() ;
@ -54,8 +55,14 @@ class PrintAttributes {
/** Prints an enum to the io_src file */
virtual void printEnum( EnumValues * in_enum) ;
bool isHeaderExcluded(const std::string& header);
void markHeaderAsVisited(const std::string& header);
protected:
const bool verboseBuild = getenv("TRICK_VERBOSE_BUILD");
const std::string skipping = color(SKIP, "Skipping ");
/** Directory to put class and enum map files */
std::string map_dir ;
@ -93,9 +100,12 @@ class PrintAttributes {
bool isFileIncluded(std::string header_file_name) ;
bool isIOFileOutOfDate(std::string header_file_name, std::string io_file_name ) ;
bool hasBeenProcessed(EnumValues& enumValues);
bool hasBeenProcessed(ClassValues& classValues);
bool hasBeenProcessed(const std::string& name, std::set<std::string>& processedSet);
bool isIgnored(ConstructValues& constructValues);
/** Adds empty header files to list of processed files. */
void addEmptyFiles() ;
std::set<std::string> getEmptyFiles();
/** Determines the io_file_name based on the given header file name
@param header_file_name = full path to header file
@ -112,9 +122,6 @@ class PrintAttributes {
/** set of external library header files */
std::set< std::string > ext_lib_io_files ;
/** set of headers that have no class/enums */
std::set< std::string > empty_header_files ;
/** map of open files to the out of date io_src file */
std::map< std::string , std::string > out_of_date_io_files ;

View File

@ -94,6 +94,11 @@ char * almostRealPath( const char * in_path ) {
}
free(file_copy_path) ;
free(dir_copy_path) ;
if (!final_path) {
std::cout << bold(color(WARNING, "Warning")) << " ICG could not resolve realpath of " << quote(bold(in_path)) << std::endl;
}
return final_path ;
}

View File

@ -10,7 +10,8 @@
enum Color {
ERROR = 31,
WARNING = 33,
INFO = 34
INFO = 34,
SKIP = 95
};
std::string trim( const std::string& str, const std::string& whitespace = " \t\n\r" ) ;