File: utilities.cpp

package info (click to toggle)
kdevelop 4%3A5.6.2-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 57,892 kB
  • sloc: cpp: 278,773; javascript: 3,558; python: 3,385; sh: 1,317; ansic: 689; xml: 273; php: 95; makefile: 40; lisp: 13; sed: 12
file content (122 lines) | stat: -rw-r--r-- 4,496 bytes parent folder | download
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
/*
   Copyright 2009 Ramón Zarazúa <killerfox512+kde@gmail.com>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
 */

#include "utilities.h"
#include <debug.h>

#include <serialization/indexedstring.h>
#include <duchain/identifier.h>
#include <duchain/duchainlock.h>
#include <duchain/duchain.h>
#include <duchain/declaration.h>
#include <duchain/forwarddeclaration.h>
#include <duchain/functiondefinition.h>
#include <duchain/classfunctiondeclaration.h>
#include <duchain/types/functiontype.h>

namespace KDevelop {
namespace CodeGenUtils {
IdentifierValidator::IdentifierValidator(DUContext* context) : QValidator(nullptr)
    , m_context(context)
{
}

IdentifierValidator::~IdentifierValidator()
{
}

QValidator::State IdentifierValidator::validate(QString& input, int&) const
{
    //I can't figure out why it wouldn't compile when I tried to use Identifier identifier();
    Identifier identifier = Identifier(IndexedString(input));

    if (identifier.isUnique())
        return Acceptable;

    DUChainReadLocker lock(DUChain::lock(), 10);
    return m_context->findLocalDeclarations(identifier, CursorInRevision::invalid(), nullptr,
                                            AbstractType::Ptr(), DUContext::NoFiltering).empty() ? Acceptable : Invalid;
}

IndexedString fetchImplementationFileForClass(const Declaration& targetClass)
{
    DUChainReadLocker lock(DUChain::lock());
    qCDebug(LANGUAGE) << "Looking for implementation file for class:" << targetClass.identifier().toString();

    DUContext* context = targetClass.internalContext();

    //If this declaration is not a user defined type, then ignore and return empty file
    if (targetClass.kind() != Declaration::Type)
        return IndexedString();

    //If this is a forward declaration attempt to resolve it.
    const Declaration* realClass = &targetClass;
    if (const auto* forward = dynamic_cast<const ForwardDeclaration*>(realClass)) {
        if (!(realClass = forward->resolve(context->topContext())))
            return IndexedString();
        context = realClass->internalContext();
    }

    const QVector<Declaration*> declarations = context->localDeclarations();

    QMap<IndexedString, unsigned int> implementationsInFile;

    for (Declaration* decl : declarations) {
        ///@todo check for static variable instantiation as well
        if (auto* classFun = dynamic_cast<ClassFunctionDeclaration*>(decl))
            if (FunctionDefinition* def = FunctionDefinition::definition(classFun)) {
                qCDebug(LANGUAGE) << "Definition For declaration in:" << def->url().toUrl();
                ++implementationsInFile[def->url()];
            }
    }

    QMultiMap<unsigned int, IndexedString> sorter;
    for (auto it = implementationsInFile.constBegin(), end = implementationsInFile.constEnd(); it != end; ++it) {
        const IndexedString& file = it.key();
        unsigned int count = it.value();
        sorter.insert(count, file);
    }
    QList<IndexedString> sortedFiles = sorter.values();

    //If there are no methods, then just return the file the declaration is in
    if (sortedFiles.empty())
        return context->url();

    if (sortedFiles.size() == 1)
        return sortedFiles[0];

    const QList<IndexedString> tiedFiles = sorter.values(sorter.end().key());
    if (tiedFiles.size() > 1) {
        //Return the file that has the most uses
        const auto uses = realClass->uses();

        IndexedString mostUsesFile;
        unsigned int mostUses = 0;
        for (const IndexedString& currentFile : tiedFiles) {
            if (static_cast<unsigned int>(uses[currentFile].size()) > mostUses) {
                mostUses = uses[currentFile].size();
                mostUsesFile = currentFile;
            }
        }

        return mostUsesFile;
    } else
        return sortedFiles.back();
}
}
}