diff options
Diffstat (limited to 'docs/tool/Modules/NaturalDocs/SymbolTable')
6 files changed, 1602 insertions, 0 deletions
diff --git a/docs/tool/Modules/NaturalDocs/SymbolTable/File.pm b/docs/tool/Modules/NaturalDocs/SymbolTable/File.pm new file mode 100644 index 00000000..71f93645 --- /dev/null +++ b/docs/tool/Modules/NaturalDocs/SymbolTable/File.pm @@ -0,0 +1,186 @@ +############################################################################### +# +# Package: NaturalDocs::SymbolTable::File +# +############################################################################### +# +# A class representing a file, keeping track of what symbols and references are defined in it. +# +############################################################################### + +# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure +# Natural Docs is licensed under the GPL + +use strict; +use integer; + +package NaturalDocs::SymbolTable::File; + + +############################################################################### +# Group: Implementation + +# +# Constants: Members +# +# The class is implemented as a blessed arrayref. The following constants are its members. +# +# SYMBOLS - An existence hashref of the <SymbolStrings> it defines. +# REFERENCES - An existence hashref of the <ReferenceStrings> in the file. +# + +# DEPENDENCY: New() depends on the order of these constants. If they change, New() has to be updated. +use constant SYMBOLS => 0; +use constant REFERENCES => 1; + + +############################################################################### +# Group: Modification Functions + + +# +# Function: New +# +# Creates and returns a new object. +# +sub New + { + my $package = shift; + + # Let's make it safe, since normally you can pass values to New. Having them just be ignored would be an obscure error. + if (scalar @_) + { die "You can't pass values to NaturalDocs::SymbolTable::File->New()\n"; }; + + # DEPENDENCY: This code depends on the order of the member constants. + my $object = [ { }, { } ]; + bless $object, $package; + + return $object; + }; + + +# +# Function: AddSymbol +# +# Adds a <SymbolString> definition. +# +# Parameters: +# +# symbol - The <SymbolString> being added. +# +sub AddSymbol #(symbol) + { + my ($self, $symbol) = @_; + $self->[SYMBOLS]{$symbol} = 1; + }; + + +# +# Function: DeleteSymbol +# +# Removes a <SymbolString> definition. +# +# Parameters: +# +# symbol - The <SymbolString> to delete. +# +sub DeleteSymbol #(symbol) + { + my ($self, $symbol) = @_; + delete $self->[SYMBOLS]{$symbol}; + }; + + +# +# Function: AddReference +# +# Adds a reference definition. +# +# Parameters: +# +# referenceString - The <ReferenceString> being added. +# +sub AddReference #(referenceString) + { + my ($self, $referenceString) = @_; + $self->[REFERENCES]{$referenceString} = 1; + }; + + +# +# Function: DeleteReference +# +# Removes a reference definition. +# +# Parameters: +# +# referenceString - The <ReferenceString> to delete. +# +sub DeleteReference #(referenceString) + { + my ($self, $referenceString) = @_; + delete $self->[REFERENCES]{$referenceString}; + }; + + + +############################################################################### +# Group: Information Functions + + +# +# Function: HasAnything +# +# Returns whether the file has any symbol or reference definitions at all. +# +sub HasAnything + { + return (scalar keys %{$_[0]->[SYMBOLS]} || scalar keys %{$_[0]->[REFERENCES]}); + }; + +# +# Function: Symbols +# +# Returns an array of all the <SymbolStrings> defined in this file. If none, returns an empty array. +# +sub Symbols + { + return keys %{$_[0]->[SYMBOLS]}; + }; + + +# +# Function: References +# +# Returns an array of all the <ReferenceStrings> defined in this file. If none, returns an empty array. +# +sub References + { + return keys %{$_[0]->[REFERENCES]}; + }; + + +# +# Function: DefinesSymbol +# +# Returns whether the file defines the passed <SymbolString> or not. +# +sub DefinesSymbol #(symbol) + { + my ($self, $symbol) = @_; + return exists $self->[SYMBOLS]{$symbol}; + }; + + +# +# Function: DefinesReference +# +# Returns whether the file defines the passed <ReferenceString> or not. +# +sub DefinesReference #(referenceString) + { + my ($self, $referenceString) = @_; + return exists $self->[REFERENCES]{$referenceString}; + }; + +1; diff --git a/docs/tool/Modules/NaturalDocs/SymbolTable/IndexElement.pm b/docs/tool/Modules/NaturalDocs/SymbolTable/IndexElement.pm new file mode 100644 index 00000000..e54ce44c --- /dev/null +++ b/docs/tool/Modules/NaturalDocs/SymbolTable/IndexElement.pm @@ -0,0 +1,522 @@ +############################################################################### +# +# Class: NaturalDocs::SymbolTable::IndexElement +# +############################################################################### +# +# A class representing part of an indexed symbol. +# +############################################################################### + +# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure +# Natural Docs is licensed under the GPL + +use Tie::RefHash; + +use strict; +use integer; + + +package NaturalDocs::SymbolTable::IndexElement; + + +# +# Topic: How IndexElements Work +# +# This is a little tricky, so make sure you understand this. Indexes are sorted by symbol, then packages, then file. If there is only +# one package for a symbol, or one file definition for a package/symbol, they are added inline to the entry. However, if there are +# multiple packages or files, the function for it returns an arrayref of IndexElements instead. Which members are defined and +# undefined should follow common sense. For example, if a symbol is defined in multiple packages, the symbol's IndexElement +# will not define <File()>, <Type()>, or <Prototype()>; those will be defined in child elements. Similarly, the child elements will +# not define <Symbol()> since it's redundant. +# +# Diagrams may be clearer. If a member isn't listed for an element, it isn't defined. +# +# A symbol that only has one package and file: +# > [Element] +# > - Symbol +# > - Package +# > - File +# > - Type +# > - Prototype +# > - Summary +# +# A symbol that is defined by multiple packages, each with only one file: +# > [Element] +# > - Symbol +# > - Package +# > [Element] +# > - Package +# > - File +# > - Type +# > - Prototype +# > - Summary +# > [Element] +# > - ... +# +# A symbol that is defined by one package, but has multiple files +# > [Element] +# > - Symbol +# > - Package +# > - File +# > [Element] +# > - File +# > - Type +# > - Protype +# > - Summary +# > [Element] +# > - ... +# +# A symbol that is defined by multiple packages which have multiple files: +# > [Element] +# > - Symbol +# > - Package +# > [Element] +# > - Package +# > - File +# > [Element] +# > - File +# > - Type +# > - Prototype +# > - Summary +# > [Element] +# > - ... +# > [Element] +# > - ... +# +# Why is it done this way?: +# +# Because it makes it easier to generate nice indexes since all the splitting and combining is done for you. If a symbol +# has only one package, you just want to link to it, you don't want to break out a subindex for just one package. However, if +# it has multiple package, you do want the subindex and to link to each one individually. Use <HasMultiplePackages()> and +# <HasMultipleFiles()> to determine whether you need to add a subindex for it. +# +# +# Combining Properties: +# +# All IndexElements also have combining properties set. +# +# CombinedType - The general <TopicType> of the entry. Conflicts combine into <TOPIC_GENERAL>. +# PackageSeparator - The package separator symbol of the entry. Conflicts combine into a dot. +# +# So if an IndexElement only has one definition, <CombinedType()> is the same as the <TopicType> and <PackageSeparator()> +# is that of the definition's language. If other definitions are added and they have the same properties, the combined properties +# will remain the same. However, if they're different, they switch values as noted above. +# +# +# Sortable Symbol: +# +# <SortableSymbol()> is a pseudo-combining property. There were a few options for dealing with multiple languages defining +# the same symbol but stripping different prefixes off it, but ultimately I decided to go with whatever the language does that +# has the most definitions. There's not likely to be many conflicts here in the real world; probably the only thing would be +# defining it in a text file and forgetting to specify the prefixes to strip there too. So this works. +# +# Ties are broken pretty much randomly, except that text files always lose if its one of the options. +# +# It's a pseudo-combining property because it's done after the IndexElements are all filled in and only stored in the top-level +# ones. +# + + +############################################################################### +# Group: Implementation + +# +# Constants: Members +# +# The class is implemented as a blessed arrayref. The following constants are its members. +# +# SYMBOL - The <SymbolString> without the package portion. +# PACKAGE - The package <SymbolString>. Will be a package <SymbolString>, undef for global, or an arrayref of +# <NaturalDocs::SymbolTable::IndexElement> objects if multiple packages define the symbol. +# FILE - The <FileName> the package/symbol is defined in. Will be the file name or an arrayref of +# <NaturalDocs::SymbolTable::IndexElements> if multiple files define the package/symbol. +# TYPE - The package/symbol/file <TopicType>. +# PROTOTYPE - The package/symbol/file prototype, or undef if not applicable. +# SUMMARY - The package/symbol/file summary, or undef if not applicable. +# COMBINED_TYPE - The combined <TopicType> of the element. +# PACKAGE_SEPARATOR - The combined package separator symbol of the element. +# SORTABLE_SYMBOL - The sortable symbol as a text string. +# IGNORED_PREFIX - The part of the symbol that was stripped off to make the sortable symbol. +# +use NaturalDocs::DefineMembers 'SYMBOL', 'Symbol()', + 'PACKAGE', 'Package()', + 'FILE', 'File()', + 'TYPE', 'Type()', + 'PROTOTYPE', 'Prototype()', + 'SUMMARY', 'Summary()', + 'COMBINED_TYPE', 'CombinedType()', + 'PACKAGE_SEPARATOR', 'PackageSeparator()', + 'SORTABLE_SYMBOL', 'SortableSymbol()', + 'IGNORED_PREFIX', 'IgnoredPrefix()'; +# DEPENDENCY: New() depends on the order of these constants and that there is no inheritance.. + + +############################################################################### +# Group: Modification Functions + +# +# Function: New +# +# Returns a new object. +# +# This should only be used for creating an entirely new symbol. You should *not* pass arrayrefs as package or file parameters +# if you are calling this externally. Use <Merge()> instead. +# +# Parameters: +# +# symbol - The <SymbolString> without the package portion. +# package - The package <SymbolString>, or undef for global. +# file - The symbol's definition file. +# type - The symbol's <TopicType>. +# prototype - The symbol's prototype, if applicable. +# summary - The symbol's summary, if applicable. +# +# Optional Parameters: +# +# These parameters don't need to be specified. You should ignore them when calling this externally. +# +# combinedType - The symbol's combined <TopicType>. +# packageSeparator - The symbol's combined package separator symbol. +# +sub New #(symbol, package, file, type, prototype, summary, combinedType, packageSeparator) + { + # DEPENDENCY: This depends on the parameter list being in the same order as the constants. + + my $self = shift; + + my $object = [ @_ ]; + bless $object, $self; + + if (!defined $object->[COMBINED_TYPE]) + { $object->[COMBINED_TYPE] = $object->[TYPE]; }; + + if (!defined $object->[PACKAGE_SEPARATOR]) + { + if ($object->[TYPE] eq ::TOPIC_FILE()) + { $object->[PACKAGE_SEPARATOR] = '.'; } + else + { + $object->[PACKAGE_SEPARATOR] = NaturalDocs::Languages->LanguageOf($object->[FILE])->PackageSeparator(); + }; + }; + + return $object; + }; + + +# +# Function: Merge +# +# Adds another definition of the same symbol. Perhaps it has a different package or defining file. +# +# Parameters: +# +# package - The package <SymbolString>, or undef for global. +# file - The symbol's definition file. +# type - The symbol's <TopicType>. +# prototype - The symbol's protoype if applicable. +# summary - The symbol's summary if applicable. +# +sub Merge #(package, file, type, prototype, summary) + { + my ($self, $package, $file, $type, $prototype, $summary) = @_; + + # If there's only one package... + if (!$self->HasMultiplePackages()) + { + # If there's one package and it's the same as the new one... + if ($package eq $self->Package()) + { + $self->MergeFile($file, $type, $prototype, $summary); + } + + # If there's one package and the new one is different... + else + { + my $selfDefinition = NaturalDocs::SymbolTable::IndexElement->New(undef, $self->Package(), $self->File(), + $self->Type(), $self->Prototype(), + $self->Summary(), $self->CombinedType(), + $self->PackageSeparator()); + my $newDefinition = NaturalDocs::SymbolTable::IndexElement->New(undef, $package, $file, $type, $prototype, + $summary); + + $self->[PACKAGE] = [ $selfDefinition, $newDefinition ]; + $self->[FILE] = undef; + $self->[TYPE] = undef; + $self->[PROTOTYPE] = undef; + $self->[SUMMARY] = undef; + + if ($newDefinition->Type() ne $self->CombinedType()) + { $self->[COMBINED_TYPE] = ::TOPIC_GENERAL(); }; + if ($newDefinition->PackageSeparator() ne $self->PackageSeparator()) + { $self->[PACKAGE_SEPARATOR] = '.'; }; + }; + } + + # If there's more than one package... + else + { + # See if the new package is one of them. + my $selfPackages = $self->Package(); + my $matchingPackage; + + foreach my $testPackage (@$selfPackages) + { + if ($package eq $testPackage->Package()) + { + $testPackage->MergeFile($file, $type, $prototype, $summary);; + return; + }; + }; + + my $newDefinition = NaturalDocs::SymbolTable::IndexElement->New(undef, $package, $file, $type, $prototype, + $summary); + push @{$self->[PACKAGE]}, $newDefinition; + + if ($newDefinition->Type() ne $self->CombinedType()) + { $self->[COMBINED_TYPE] = ::TOPIC_GENERAL(); }; + if ($newDefinition->PackageSeparator() ne $self->PackageSeparator()) + { $self->[PACKAGE_SEPARATOR] = '.'; }; + }; + }; + + +# +# Function: Sort +# +# Sorts the package and file lists of the symbol. +# +sub Sort + { + my $self = shift; + + if ($self->HasMultipleFiles()) + { + @{$self->[FILE]} = sort { ::StringCompare($a->File(), $b->File()) } @{$self->File()}; + } + + elsif ($self->HasMultiplePackages()) + { + @{$self->[PACKAGE]} = sort { ::StringCompare( $a->Package(), $b->Package()) } @{$self->[PACKAGE]}; + + foreach my $packageElement ( @{$self->[PACKAGE]} ) + { + if ($packageElement->HasMultipleFiles()) + { $packageElement->Sort(); }; + }; + }; + }; + + +# +# Function: MakeSortableSymbol +# +# Generates <SortableSymbol()> and <IgnoredPrefix()>. Should only be called after everything is merged. +# +sub MakeSortableSymbol + { + my $self = shift; + + my $finalLanguage; + + if ($self->HasMultiplePackages() || $self->HasMultipleFiles()) + { + # Collect all the files that define this symbol. + + my @files; + + if ($self->HasMultipleFiles()) + { + my $fileElements = $self->File(); + + foreach my $fileElement (@$fileElements) + { push @files, $fileElement->File(); }; + } + else # HasMultiplePackages + { + my $packages = $self->Package(); + + foreach my $package (@$packages) + { + if ($package->HasMultipleFiles()) + { + my $fileElements = $package->File(); + + foreach my $fileElement (@$fileElements) + { push @files, $fileElement->File(); }; + } + else + { push @files, $package->File(); }; + }; + }; + + + # Determine which language defines it the most. + + # Keys are language objects, values are counts. + my %languages; + tie %languages, 'Tie::RefHash'; + + foreach my $file (@files) + { + my $language = NaturalDocs::Languages->LanguageOf($file); + + if (exists $languages{$language}) + { $languages{$language}++; } + else + { $languages{$language} = 1; }; + }; + + my $topCount = 0; + my @topLanguages; + + while (my ($language, $count) = each %languages) + { + if ($count > $topCount) + { + $topCount = $count; + @topLanguages = ( $language ); + } + elsif ($count == $topCount) + { + push @topLanguages, $language; + }; + }; + + if (scalar @topLanguages == 1) + { $finalLanguage = $topLanguages[0]; } + else + { + if ($topLanguages[0]->Name() ne 'Text File') + { $finalLanguage = $topLanguages[0]; } + else + { $finalLanguage = $topLanguages[1]; }; + }; + } + + else # !hasMultiplePackages && !hasMultipleFiles + { $finalLanguage = NaturalDocs::Languages->LanguageOf($self->File()); }; + + my $textSymbol = NaturalDocs::SymbolString->ToText($self->Symbol(), $self->PackageSeparator()); + my $ignoredPrefixLength = $finalLanguage->IgnoredPrefixLength($textSymbol, $self->CombinedType()); + + if ($ignoredPrefixLength) + { + $self->[IGNORED_PREFIX] = substr($textSymbol, 0, $ignoredPrefixLength); + $self->[SORTABLE_SYMBOL] = substr($textSymbol, $ignoredPrefixLength); + } + else + { $self->[SORTABLE_SYMBOL] = $textSymbol; }; + }; + + + +############################################################################### +# +# Functions: Information Functions +# +# Symbol - Returns the <SymbolString> without the package portion. +# Package - If <HasMultiplePackages()> is true, returns an arrayref of <NaturalDocs::SymbolTable::IndexElement> objects. +# Otherwise returns the package <SymbolString>, or undef if global. +# File - If <HasMultipleFiles()> is true, returns an arrayref of <NaturalDocs::SymbolTable::IndexElement> objects. Otherwise +# returns the name of the definition file. +# Type - Returns the <TopicType> of the package/symbol/file, if applicable. +# Prototype - Returns the prototype of the package/symbol/file, if applicable. +# Summary - Returns the summary of the package/symbol/file, if applicable. +# CombinedType - Returns the combined <TopicType> of the element. +# PackageSeparator - Returns the combined package separator symbol of the element. +# SortableSymbol - Returns the sortable symbol as a text string. Only available after calling <MakeSortableSymbol()>. +# IgnoredPrefix - Returns the part of the symbol that was stripped off to make the <SortableSymbol()>, or undef if none. +# Only available after calling <MakeSortableSymbol()>. +# + +# Function: HasMultiplePackages +# Returns whether <Packages()> is broken out into more elements. +sub HasMultiplePackages + { return ref($_[0]->[PACKAGE]); }; + +# Function: HasMultipleFiles +# Returns whether <File()> is broken out into more elements. +sub HasMultipleFiles + { return ref($_[0]->[FILE]); }; + + + + + + +############################################################################### +# Group: Support Functions + +# +# Function: MergeFile +# +# Adds another definition of the same package/symbol. Perhaps the file is different. +# +# Parameters: +# +# file - The package/symbol's definition file. +# type - The package/symbol's <TopicType>. +# prototype - The package/symbol's protoype if applicable. +# summary - The package/symbol's summary if applicable. +# +sub MergeFile #(file, type, prototype, summary) + { + my ($self, $file, $type, $prototype, $summary) = @_; + + # If there's only one file... + if (!$self->HasMultipleFiles()) + { + # If there's one file and it's the different from the new one... + if ($file ne $self->File()) + { + my $selfDefinition = NaturalDocs::SymbolTable::IndexElement->New(undef, undef, $self->File(), $self->Type(), + $self->Prototype(), $self->Summary(), + $self->CombinedType(), + $self->PackageSeparator()); + my $newDefinition = NaturalDocs::SymbolTable::IndexElement->New(undef, undef, $file, $type, $prototype, + $summary); + + $self->[FILE] = [ $selfDefinition, $newDefinition ]; + $self->[TYPE] = undef; + $self->[PROTOTYPE] = undef; + $self->[SUMMARY] = undef; + + if ($newDefinition->Type() ne $self->CombinedType()) + { $self->[COMBINED_TYPE] = ::TOPIC_GENERAL(); }; + if ($newDefinition->PackageSeparator() ne $self->PackageSeparator()) + { $self->[PACKAGE_SEPARATOR] = '.'; }; + } + + # If the file was the same, just ignore the duplicate in the index. + } + + # If there's more than one file... + else + { + # See if the new file is one of them. + my $files = $self->File(); + + foreach my $testElement (@$files) + { + if ($testElement->File() eq $file) + { + # If the new file's already in the index, ignore the duplicate. + return; + }; + }; + + my $newDefinition = NaturalDocs::SymbolTable::IndexElement->New(undef, undef, $file, $type, $prototype, + $summary); + push @{$self->[FILE]}, $newDefinition; + + if ($newDefinition->Type() ne $self->CombinedType()) + { $self->[COMBINED_TYPE] = ::TOPIC_GENERAL(); }; + if ($newDefinition->PackageSeparator() ne $self->PackageSeparator()) + { $self->[PACKAGE_SEPARATOR] = '.'; }; + }; + }; + + +1; diff --git a/docs/tool/Modules/NaturalDocs/SymbolTable/Reference.pm b/docs/tool/Modules/NaturalDocs/SymbolTable/Reference.pm new file mode 100644 index 00000000..ed8c3059 --- /dev/null +++ b/docs/tool/Modules/NaturalDocs/SymbolTable/Reference.pm @@ -0,0 +1,273 @@ +############################################################################### +# +# Package: NaturalDocs::SymbolTable::Reference +# +############################################################################### +# +# A class representing a symbol or a potential symbol. +# +############################################################################### + +# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure +# Natural Docs is licensed under the GPL + +use strict; +use integer; + +package NaturalDocs::SymbolTable::Reference; + + +############################################################################### +# Group: Implementation + +# +# Constants: Members +# +# The class is implemented as a blessed arrayref. The following constants are its members. +# +# DEFINITIONS - An existence hashref of the <FileNames> that define this reference. +# INTERPRETATIONS - A hashref of the possible interpretations of this reference. The keys are the <SymbolStrings> +# and the values are the scores. +# CURRENT_INTERPRETATION - The interpretation currently used as the reference target. It will be the interpretation with +# the highest score that is actually defined. If none are defined, this item will be undef. +# + +# DEPENDENCY: New() depends on the order of these constants. If they change, New() has to be updated. +use constant DEFINITIONS => 0; +use constant INTERPRETATIONS => 1; +use constant CURRENT_INTERPRETATION => 2; + + +############################################################################### +# Group: Modification Functions + + +# +# Function: New +# +# Creates and returns a new object. +# +sub New + { + my $package = shift; + + # Let's make it safe, since normally you can pass values to New. Having them just be ignored would be an obscure error. + if (scalar @_) + { die "You can't pass values to NaturalDocs::SymbolTable::Reference->New()\n"; }; + + # DEPENDENCY: This code depends on the order of the member constants. + my $object = [ { }, { }, undef ]; + bless $object, $package; + + return $object; + }; + + +# +# Function: AddDefinition +# +# Adds a reference definition. +# +# Parameters: +# +# file - The <FileName> that defines the reference. +# +sub AddDefinition #(file) + { + my ($self, $file) = @_; + + $self->[DEFINITIONS]{$file} = 1; + }; + + +# +# Function: DeleteDefinition +# +# Removes a reference definition. +# +# Parameters: +# +# file - The <FileName> which has the definition to delete. +# +sub DeleteDefinition #(file) + { + my ($self, $file) = @_; + + delete $self->[DEFINITIONS]{$file}; + }; + + +# +# Function: AddInterpretation +# +# Adds a symbol that this reference can be interpreted as. +# +# Parameters: +# +# symbol - The <SymbolString>. +# score - The score of this interpretation. +# +sub AddInterpretation #(symbol, score) + { + my ($self, $symbol, $score) = @_; + + $self->[INTERPRETATIONS]{$symbol} = $score; + }; + + +# +# Function: DeleteInterpretation +# +# Deletes a symbol that this reference can be interpreted as. +# +# Parameters: +# +# symbol - The <SymbolString> to delete. +# +sub DeleteInterpretation #(symbol) + { + my ($self, $symbol) = @_; + + delete $self->[INTERPRETATIONS]{$symbol}; + }; + + +# +# Function: DeleteAllInterpretationsButCurrent +# +# Deletes all interpretations except for the current one. +# +sub DeleteAllInterpretationsButCurrent + { + my $self = shift; + + if ($self->HasCurrentInterpretation()) + { + my $score = $self->CurrentScore(); + + # Fastest way to clear a hash except for one item? Make a new hash with just that item. + %{$self->[INTERPRETATIONS]} = ( $self->[CURRENT_INTERPRETATION] => $score ); + }; + }; + + +# +# Function: SetCurrentInterpretation +# +# Changes the current interpretation. The new one must already have been added via <AddInterpretation()>. +# +# Parameters: +# +# symbol - The <SymbolString>l to make the current interpretation. Can be set to undef to clear it. +# +sub SetCurrentInterpretation #(symbol) + { + my ($self, $symbol) = @_; + + $self->[CURRENT_INTERPRETATION] = $symbol; + }; + + +############################################################################### +# Group: Information Functions + + +# +# Function: Definitions +# +# Returns an array of all the <FileNames> that define this reference. If none do, returns an empty array. +# +sub Definitions + { + return keys %{$_[0]->[DEFINITIONS]}; + }; + + +# +# Function: IsDefined +# +# Returns whether the reference has any definitions or not. +# +sub IsDefined + { + return scalar keys %{$_[0]->[DEFINITIONS]}; + }; + + +# +# Function: IsDefinedIn +# +# Returns whether the reference is defined in the passed <FileName>. +# +sub IsDefinedIn #(file) + { + my ($self, $file) = @_; + + return exists $self->[DEFINITIONS]{$file}; + }; + + +# +# Function: Interpretations +# +# Returns an array of all the <SymbolStrings> that this reference can be interpreted as. If none, returns an empty array. +# +sub Interpretations + { + return keys %{$_[0]->[INTERPRETATIONS]}; + }; + + +# +# Function: InterpretationsAndScores +# +# Returns a hash of all the <SymbolStrings> that this reference can be interpreted as and their scores. The keys are the <SymbolStrings> +# and the values are the scores. If none, returns an empty hash. +# +sub InterpretationsAndScores + { + return %{$_[0]->[INTERPRETATIONS]}; + }; + + +# +# Function: HasCurrentInterpretation +# +# Returns whether the reference has a current interpretation or not. +# +sub HasCurrentInterpretation + { + return defined $_[0]->[CURRENT_INTERPRETATION]; + }; + + +# +# Function: CurrentInterpretation +# +# Returns the <SymbolString> of the current interpretation, or undef if none. +# +sub CurrentInterpretation + { + return $_[0]->[CURRENT_INTERPRETATION]; + }; + + +# +# Function: CurrentScore +# +# Returns the score of the current interpretation, or undef if none. +# +sub CurrentScore + { + my $self = shift; + + if (defined $self->[CURRENT_INTERPRETATION]) + { + return $self->[INTERPRETATIONS]{ $self->[CURRENT_INTERPRETATION] }; + } + else + { return undef; }; + }; + + +1; diff --git a/docs/tool/Modules/NaturalDocs/SymbolTable/ReferenceTarget.pm b/docs/tool/Modules/NaturalDocs/SymbolTable/ReferenceTarget.pm new file mode 100644 index 00000000..a1b2b0a5 --- /dev/null +++ b/docs/tool/Modules/NaturalDocs/SymbolTable/ReferenceTarget.pm @@ -0,0 +1,97 @@ +############################################################################### +# +# Class: NaturalDocs::SymbolTable::ReferenceTarget +# +############################################################################### +# +# A class for storing information about a reference target. +# +############################################################################### + +# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure +# Natural Docs is licensed under the GPL + +use strict; +use integer; + +package NaturalDocs::SymbolTable::ReferenceTarget; + + +############################################################################### +# Group: Implementation + +# +# Constants: Members +# +# The class is implemented as a blessed arrayref. The following constants are its members. +# +# SYMBOL - The target <SymbolString>. +# FILE - The <FileName> the target is defined in. +# TYPE - The target <TopicType>. +# PROTOTYPE - The target's prototype, or undef if none. +# SUMMARY - The target's summary, or undef if none. +# + +# DEPENDENCY: New() depends on the order of these constants. If they change, New() has to be updated. +use constant SYMBOL => 0; +use constant FILE => 1; +use constant TYPE => 2; +use constant PROTOTYPE => 3; +use constant SUMMARY => 4; + +############################################################################### +# Group: Functions + + +# +# Function: New +# +# Creates and returns a new object. +# +# Parameters: +# +# symbol - The target <SymbolString>. +# file - The <FileName> the target is defined in. +# type - The <TopicType> of the target symbol. +# prototype - The target's prototype. Set to undef if not defined or not applicable. +# summary - The target's summary. Set to undef if not defined or not applicable. +# +sub New #(symbol, file, type, prototype, summary) + { + # DEPENDENCY: This code depends on the order of the member constants. + + my $package = shift; + + my $object = [ @_ ]; + bless $object, $package; + + return $object; + }; + + +# Function: Symbol +# Returns the target's <SymbolString>. +sub Symbol + { return $_[0]->[SYMBOL]; }; + +# Function: File +# Returns the <FileName> the target is defined in. +sub File + { return $_[0]->[FILE]; }; + +# Function: Type +# Returns the target's <TopicType>. +sub Type + { return $_[0]->[TYPE]; }; + +# Function: Prototype +# Returns the target's prototype, or undef if not defined or not applicable. +sub Prototype + { return $_[0]->[PROTOTYPE]; }; + +# Function: Summary +# Returns the target's summary, or undef if not defined or not applicable. +sub Summary + { return $_[0]->[SUMMARY]; }; + +1; diff --git a/docs/tool/Modules/NaturalDocs/SymbolTable/Symbol.pm b/docs/tool/Modules/NaturalDocs/SymbolTable/Symbol.pm new file mode 100644 index 00000000..f12858df --- /dev/null +++ b/docs/tool/Modules/NaturalDocs/SymbolTable/Symbol.pm @@ -0,0 +1,428 @@ +############################################################################### +# +# Package: NaturalDocs::SymbolTable::Symbol +# +############################################################################### +# +# A class representing a symbol or a potential symbol. +# +############################################################################### + +# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure +# Natural Docs is licensed under the GPL + +use strict; +use integer; + +package NaturalDocs::SymbolTable::Symbol; + + +############################################################################### +# Group: Implementation + +# +# Constants: Members +# +# The class is implemented as a blessed arrayref. The following constants are its members. +# +# DEFINITIONS - A hashref of all the files which define this symbol. The keys are the <FileNames>, and the values are +# <NaturalDocs::SymbolTable::SymbolDefinition> objects. If no files define this symbol, this item will +# be undef. +# GLOBAL_DEFINITION - The <FileName> which defines the global version of the symbol, which is what is used if +# a file references the symbol but does not have its own definition. If there are no definitions, this +# item will be undef. +# REFERENCES - A hashref of the references that can be interpreted as this symbol. This doesn't mean these +# references necessarily are. The keys are the reference strings, and the values are the scores of +# the interpretations. If no references can be interpreted as this symbol, this item will be undef. +# +use constant DEFINITIONS => 0; +use constant GLOBAL_DEFINITION => 1; +use constant REFERENCES => 2; + + +############################################################################### +# Group: Modification Functions + +# +# Function: New +# +# Creates and returns a new object. +# +sub New + { + my $package = shift; + + # Let's make it safe, since normally you can pass values to New. Having them just be ignored would be an obscure error. + if (scalar @_) + { die "You can't pass values to NaturalDocs::SymbolTable::Symbol->New()\n"; }; + + my $object = [ undef, undef, undef ]; + bless $object, $package; + + return $object; + }; + +# +# Function: AddDefinition +# +# Adds a symbol definition. If this is the first definition for this symbol, it will become the global definition. If the definition +# already exists for the file, it will be ignored. +# +# Parameters: +# +# file - The <FileName> that defines the symbol. +# type - The <TopicType> of the definition. +# prototype - The prototype of the definition, if applicable. Undef otherwise. +# summary - The summary for the definition, if applicable. Undef otherwise. +# +# Returns: +# +# Whether this provided the first definition for this symbol. +# +sub AddDefinition #(file, type, prototype, summary) + { + my ($self, $file, $type, $prototype, $summary) = @_; + + my $isFirst; + + if (!defined $self->[DEFINITIONS]) + { + $self->[DEFINITIONS] = { }; + $self->[GLOBAL_DEFINITION] = $file; + $isFirst = 1; + }; + + if (!exists $self->[DEFINITIONS]{$file}) + { + $self->[DEFINITIONS]{$file} = NaturalDocs::SymbolTable::SymbolDefinition->New($type, $prototype, $summary); + }; + + return $isFirst; + }; + + +# +# Function: ChangeDefinition +# +# Changes the information about an existing definition. +# +# Parameters: +# +# file - The <FileName> that defines the symbol. Must exist. +# type - The new <TopicType> of the definition. +# prototype - The new prototype of the definition, if applicable. Undef otherwise. +# summary - The new summary of the definition, if applicable. Undef otherwise. +# +sub ChangeDefinition #(file, type, prototype, summary) + { + my ($self, $file, $type, $prototype, $summary) = @_; + + if (defined $self->[DEFINITIONS] && + exists $self->[DEFINITIONS]{$file}) + { + $self->[DEFINITIONS]{$file}->SetType($type); + $self->[DEFINITIONS]{$file}->SetPrototype($prototype); + $self->[DEFINITIONS]{$file}->SetSummary($summary); + }; + }; + + +# +# Function: DeleteDefinition +# +# Removes a symbol definition. If the definition served as the global definition, a new one will be selected. +# +# Parameters: +# +# file - The <FileName> which contains definition to delete. +# +# Returns: +# +# Whether that was the only definition, and the symbol is now undefined. +# +sub DeleteDefinition #(file) + { + my ($self, $file) = @_; + + # If there are no definitions... + if (!defined $self->[DEFINITIONS]) + { return undef; }; + + delete $self->[DEFINITIONS]{$file}; + + # If there are no more definitions... + if (!scalar keys %{$self->[DEFINITIONS]}) + { + $self->[DEFINITIONS] = undef; + + # If definitions was previously defined, and now is empty, we can safely assume that the global definition was just deleted + # without checking it against $file. + + $self->[GLOBAL_DEFINITION] = undef; + + return 1; + } + + # If there are more definitions and the global one was just deleted... + elsif ($self->[GLOBAL_DEFINITION] eq $file) + { + # Which one becomes global is pretty much random. + $self->[GLOBAL_DEFINITION] = (keys %{$self->[DEFINITIONS]})[0]; + return undef; + }; + }; + + +# +# Function: AddReference +# +# Adds a reference that can be interpreted as this symbol. It can be, but not necessarily is. +# +# Parameters: +# +# referenceString - The string of the reference. +# score - The score of this interpretation. +# +sub AddReference #(referenceString, score) + { + my ($self, $referenceString, $score) = @_; + + if (!defined $self->[REFERENCES]) + { $self->[REFERENCES] = { }; }; + + $self->[REFERENCES]{$referenceString} = $score; + }; + + +# +# Function: DeleteReference +# +# Deletes a reference that can be interpreted as this symbol. +# +# Parameters: +# +# referenceString - The string of the reference to delete. +# +sub DeleteReference #(referenceString) + { + my ($self, $referenceString) = @_; + + # If there are no definitions... + if (!defined $self->[REFERENCES]) + { return; }; + + delete $self->[REFERENCES]{$referenceString}; + + # If there are no more definitions... + if (!scalar keys %{$self->[REFERENCES]}) + { + $self->[REFERENCES] = undef; + }; + }; + + +# +# Function: DeleteAllReferences +# +# Removes all references that can be interpreted as this symbol. +# +sub DeleteAllReferences + { + $_[0]->[REFERENCES] = undef; + }; + + +############################################################################### +# Group: Information Functions + +# +# Function: IsDefined +# +# Returns whether the symbol is defined anywhere or not. If it's not, that means it's just a potential interpretation of a +# reference. +# +sub IsDefined + { + return defined $_[0]->[GLOBAL_DEFINITION]; + }; + +# +# Function: IsDefinedIn +# +# Returns whether the symbol is defined in the passed <FileName>. +# +sub IsDefinedIn #(file) + { + my ($self, $file) = @_; + return ($self->IsDefined() && exists $self->[DEFINITIONS]{$file}); + }; + + +# +# Function: Definitions +# +# Returns an array of all the <FileNames> that define this symbol. If none do, will return an empty array. +# +sub Definitions + { + my $self = shift; + + if ($self->IsDefined()) + { return keys %{$self->[DEFINITIONS]}; } + else + { return ( ); }; + }; + + +# +# Function: GlobalDefinition +# +# Returns the <FileName> that contains the global definition of this symbol, or undef if the symbol isn't defined. +# +sub GlobalDefinition + { + return $_[0]->[GLOBAL_DEFINITION]; + }; + + +# +# Function: TypeDefinedIn +# +# Returns the <TopicType> of the symbol defined in the passed <FileName>, or undef if it's not defined in that file. +# +sub TypeDefinedIn #(file) + { + my ($self, $file) = @_; + + if ($self->IsDefined()) + { return $self->[DEFINITIONS]{$file}->Type(); } + else + { return undef; }; + }; + + +# +# Function: GlobalType +# +# Returns the <TopicType> of the global definition, or undef if the symbol isn't defined. +# +sub GlobalType + { + my $self = shift; + + my $globalDefinition = $self->GlobalDefinition(); + + if (!defined $globalDefinition) + { return undef; } + else + { return $self->[DEFINITIONS]{$globalDefinition}->Type(); }; + }; + + +# +# Function: PrototypeDefinedIn +# +# Returns the prototype of symbol defined in the passed <FileName>, or undef if it doesn't exist or is not defined in that file. +# +sub PrototypeDefinedIn #(file) + { + my ($self, $file) = @_; + + if ($self->IsDefined()) + { return $self->[DEFINITIONS]{$file}->Prototype(); } + else + { return undef; }; + }; + + +# +# Function: GlobalPrototype +# +# Returns the prototype of the global definition. Will be undef if it doesn't exist or the symbol isn't defined. +# +sub GlobalPrototype + { + my $self = shift; + + my $globalDefinition = $self->GlobalDefinition(); + + if (!defined $globalDefinition) + { return undef; } + else + { return $self->[DEFINITIONS]{$globalDefinition}->Prototype(); }; + }; + + +# +# Function: SummaryDefinedIn +# +# Returns the summary of symbol defined in the passed <FileName>, or undef if it doesn't exist or is not defined in that file. +# +sub SummaryDefinedIn #(file) + { + my ($self, $file) = @_; + + if ($self->IsDefined()) + { return $self->[DEFINITIONS]{$file}->Summary(); } + else + { return undef; }; + }; + + +# +# Function: GlobalSummary +# +# Returns the summary of the global definition. Will be undef if it doesn't exist or the symbol isn't defined. +# +sub GlobalSummary + { + my $self = shift; + + my $globalDefinition = $self->GlobalDefinition(); + + if (!defined $globalDefinition) + { return undef; } + else + { return $self->[DEFINITIONS]{$globalDefinition}->Summary(); }; + }; + + +# +# Function: HasReferences +# +# Returns whether the symbol can be interpreted as any references. +# +sub HasReferences + { + return defined $_[0]->[REFERENCES]; + }; + +# +# Function: References +# +# Returns an array of all the reference strings that can be interpreted as this symbol. If none, will return an empty array. +# +sub References + { + if (defined $_[0]->[REFERENCES]) + { return keys %{$_[0]->[REFERENCES]}; } + else + { return ( ); }; + }; + + +# +# Function: ReferencesAndScores +# +# Returns a hash of all the references that can be interpreted as this symbol and their scores. The keys are the reference +# strings, and the values are the scores. If none, will return an empty hash. +# +sub ReferencesAndScores + { + if (defined $_[0]->[REFERENCES]) + { return %{$_[0]->[REFERENCES]}; } + else + { return ( ); }; + }; + +1; diff --git a/docs/tool/Modules/NaturalDocs/SymbolTable/SymbolDefinition.pm b/docs/tool/Modules/NaturalDocs/SymbolTable/SymbolDefinition.pm new file mode 100644 index 00000000..3992e1d1 --- /dev/null +++ b/docs/tool/Modules/NaturalDocs/SymbolTable/SymbolDefinition.pm @@ -0,0 +1,96 @@ +############################################################################### +# +# Package: NaturalDocs::SymbolTable::SymbolDefinition +# +############################################################################### +# +# A class representing a symbol definition. This does not store the definition symbol, class, or file. +# +############################################################################### + +# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure +# Natural Docs is licensed under the GPL + +use strict; +use integer; + +package NaturalDocs::SymbolTable::SymbolDefinition; + + +############################################################################### +# Group: Implementation + +# +# Constants: Members +# +# The class is implemented as a blessed arrayref. The following constants are its members. +# +# TYPE - The symbol <TopicType>. +# PROTOTYPE - The symbol's prototype, if applicable. Will be undef otherwise. +# SUMMARY - The symbol's summary, if applicable. Will be undef otherwise. +# +use constant TYPE => 0; +use constant PROTOTYPE => 1; +use constant SUMMARY => 2; +# New depends on the order of the constants. + + +############################################################################### +# Group: Functions + +# +# Function: New +# +# Creates and returns a new object. +# +# Parameters: +# +# type - The symbol <TopicType>. +# prototype - The symbol prototype, if applicable. Undef otherwise. +# summary - The symbol's summary, if applicable. Undef otherwise. +# +sub New #(type, prototype, summary) + { + # This depends on the parameter list being the same as the constant order. + + my $package = shift; + + my $object = [ @_ ]; + bless $object, $package; + + return $object; + }; + + +# Function: Type +# Returns the definition's <TopicType>. +sub Type + { return $_[0]->[TYPE]; }; + +# Function: SetType +# Changes the <TopicType>. +sub SetType #(type) + { $_[0]->[TYPE] = $_[1]; }; + +# Function: Prototype +# Returns the definition's prototype, or undef if it doesn't have one. +sub Prototype + { return $_[0]->[PROTOTYPE]; }; + +# Function: SetPrototype +# Changes the prototype. +sub SetPrototype #(prototype) + { $_[0]->[PROTOTYPE] = $_[1]; }; + +# Function: Summary +# Returns the definition's summary, or undef if it doesn't have one. +sub Summary + { return $_[0]->[SUMMARY]; }; + +# Function: SetSummary +# Changes the summary. +sub SetSummary #(summary) + { $_[0]->[SUMMARY] = $_[1]; }; + + +1; |