File: PHPDocComment.cpp

package info (click to toggle)
codelite 17.0.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 136,244 kB
  • sloc: cpp: 491,547; ansic: 280,393; php: 10,259; sh: 8,930; lisp: 7,664; vhdl: 6,518; python: 6,020; lex: 4,920; yacc: 3,123; perl: 2,385; javascript: 1,715; cs: 1,193; xml: 1,110; makefile: 804; cobol: 741; sql: 709; ruby: 620; f90: 566; ada: 534; asm: 464; fortran: 350; objc: 289; tcl: 258; java: 157; erlang: 61; pascal: 51; ml: 49; awk: 44; haskell: 36
file content (165 lines) | stat: -rw-r--r-- 5,898 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "PHPDocComment.h"
#include "PHPDocParam.h"
#include "PHPDocProperty.h"
#include "PHPDocVar.h"
#include "wxStringHash.h"
#include <algorithm>
#include <wx/regex.h>
#include <wx/tokenzr.h>

PHPDocComment::PHPDocComment(PHPSourceFile& sourceFile, const wxString& comment)
    : m_sourceFile(sourceFile)
    , m_comment(comment)
    , m_returnNullable(false)
{
    static std::unordered_set<wxString> nativeTypes;
    if(nativeTypes.empty()) {
        // List taken from https://www.php.net/manual/en/language.types.intro.php
        // Native types
        nativeTypes.insert("bool");
        nativeTypes.insert("int");
        nativeTypes.insert("float");
        nativeTypes.insert("string");
        nativeTypes.insert("array");
        nativeTypes.insert("object");
        nativeTypes.insert("iterable");
        nativeTypes.insert("callable");
        nativeTypes.insert("null");
        nativeTypes.insert("mixed");
        nativeTypes.insert("void");
        // Types that are common in documentation
        nativeTypes.insert("boolean");
        nativeTypes.insert("integer");
        nativeTypes.insert("double");
        nativeTypes.insert("real");
        nativeTypes.insert("binery");
        nativeTypes.insert("resource");
        nativeTypes.insert("number");
        nativeTypes.insert("callback");
    }

    static wxRegEx reReturnStatement(wxT("@(return)[ \t]+([\\?\\a-zA-Z_]{1}[\\|\\a-zA-Z0-9_]*)"));
    if(reReturnStatement.IsValid() && reReturnStatement.Matches(m_comment)) {
        wxString returnValue = reReturnStatement.GetMatch(m_comment, 2);
        if(returnValue.StartsWith("?")) {
            returnValue.Remove(0, 1);
            m_returnNullable = true;
        }

        wxArrayString types = ::wxStringTokenize(returnValue, "|", wxTOKEN_STRTOK);
        if(types.size() > 1) {
            // Multiple return types, guess the best match
            wxString bestMatch;
            for(size_t i = 0; i < types.size(); ++i) {
                if(bestMatch.IsEmpty() && (nativeTypes.count(types.Item(i)) == 0)) {
                    bestMatch = types.Item(i);
                    break;
                }
            }

            if(bestMatch.IsEmpty()) {
                bestMatch = types.Item(0); // just get the first match
            }
            m_returnValue = sourceFile.MakeIdentifierAbsolute(bestMatch);
        } else if(types.size() == 1) {
            m_returnValue = sourceFile.MakeIdentifierAbsolute(types.Item(0));
        }
    }

    PHPDocVar var(sourceFile, m_comment);
    if(var.IsOk()) {
        m_varType = var.GetType();
        m_varName = var.GetName();
    }

    // @param <TYPE> <NAME>
    if(m_comment.Contains("@param")) {
        PHPDocParam params(sourceFile, m_comment);
        const PHPDocParam::Vec_t& paramsVec = params.Parse();
        std::for_each(paramsVec.begin(), paramsVec.end(), [&](const std::pair<wxString, wxString>& p) {
            m_paramsArr.Add(p.second);
            m_params.insert(p);
        });
    }

    // @property-read, @property-write, @property
    if(m_comment.Contains("@property")) {
        PHPDocProperty prop(sourceFile, m_comment);
        const PHPDocProperty::Tuple_t& properties = prop.ParseParams();
        std::for_each(properties.begin(), properties.end(), [&](const PHPDocProperty::Tuple_t::value_type& vt) {
            PHPDocComment::Property property;
            property.type = std::get<0>(vt);
            property.name = std::get<1>(vt);
            property.desc = std::get<2>(vt);
            m_properties.insert(std::make_pair(property.name, property));
        });
    }

    // Attempt to parse and resolve @method entries in the PHPDoc
    ProcessMethods();
}

PHPDocComment::~PHPDocComment() {}

const wxString& PHPDocComment::GetParam(size_t n) const
{
    if(n >= m_paramsArr.GetCount()) {
        static wxString emptyString;
        return emptyString;
    }
    return m_paramsArr.Item(n);
}

const wxString& PHPDocComment::GetReturn() const { return m_returnValue; }

const bool PHPDocComment::IsReturnNullable() const { return m_returnNullable; }

const wxString& PHPDocComment::GetVar() const { return m_varType; }

const wxString& PHPDocComment::GetParam(const wxString& name) const
{
    if(m_params.count(name) == 0) {
        static wxString emptyString;
        return emptyString;
    }
    return m_params.find(name)->second;
}

void PHPDocComment::ProcessMethods()
{
    // The phpdoc for method does not conform to the PHP syntax.
    // We need to alter the signature so we can use our parse to parse
    // the signature
    // @method syntax is:
    // @method [return type] [name]([[type] [parameter]<, ...>]) [<description>]
    // While PHP's syntax is:
    // function [name] ([[type] [parameter]<, ...>]) [ : return_type ]
    PHPDocProperty property(m_sourceFile, m_comment);
    const PHPDocProperty::Tuple_t& methods = property.ParseMethods();
    std::for_each(methods.begin(), methods.end(), [&](const PHPDocProperty::Tuple_t::value_type& vt) {
        wxString returnType = std::get<0>(vt);
        wxString methodName = std::get<1>(vt);
        wxString signature = std::get<2>(vt);

        wxString strBuffer;
        strBuffer << "<?php function " << methodName << signature;
        if(!returnType.IsEmpty()) {
            strBuffer << " : " << returnType << " ";
        }
        strBuffer << " {} ";

        PHPSourceFile buffer(strBuffer, NULL);
        buffer.SetTypeAbsoluteConverter(&m_sourceFile);
        buffer.Parse();

        if(!buffer.CurrentScope()->GetChildren().empty()) {
            PHPEntityBase::Ptr_t func = *buffer.CurrentScope()->GetChildren().begin();
            if(func && func->Is(kEntityTypeFunction)) {
                if(func->Parent()) {
                    func->Parent()->RemoveChild(func);
                }
                m_methods.push_back(func);
            }
        }
    });
}