| 130 | } |
| 131 | |
| 132 | QString ClangRefactoring::moveIntoSource(const IndexedDeclaration& iDecl) |
| 133 | { |
| 134 | DUChainReadLocker lock; |
| 135 | auto decl = iDecl.data(); |
| 136 | if (!decl) { |
| 137 | return i18n("No declaration under cursor"); |
| 138 | } |
| 139 | |
| 140 | const auto headerUrl = decl->url(); |
| 141 | auto targetUrl = DocumentFinderHelpers::sourceForHeader(headerUrl.str()); |
| 142 | |
| 143 | if (targetUrl.isEmpty() || targetUrl == headerUrl.str()) { |
| 144 | // TODO: Create source file if it doesn't exist |
| 145 | return i18n("No source file available for %1.", headerUrl.str()); |
| 146 | } |
| 147 | |
| 148 | lock.unlock(); |
| 149 | const IndexedString indexedTargetUrl(targetUrl); |
| 150 | auto top |
| 151 | = DUChain::self()->waitForUpdate(headerUrl, KDevelop::TopDUContext::AllDeclarationsAndContexts); |
| 152 | auto targetTopContext |
| 153 | = DUChain::self()->waitForUpdate(indexedTargetUrl, KDevelop::TopDUContext::AllDeclarationsAndContexts); |
| 154 | lock.lock(); |
| 155 | |
| 156 | if (!targetTopContext) { |
| 157 | return i18n("Failed to update DUChain for %1.", targetUrl); |
| 158 | } |
| 159 | |
| 160 | if (!top || !iDecl.data() || iDecl.data() != decl) { |
| 161 | return i18n("Declaration lost while updating."); |
| 162 | } |
| 163 | |
| 164 | clangDebug() << "moving" << decl->qualifiedIdentifier(); |
| 165 | |
| 166 | if (!validCandidateToMoveIntoSource(decl)) { |
| 167 | return i18n("Cannot create definition for this declaration."); |
| 168 | } |
| 169 | |
| 170 | auto otherCtx = decl->internalContext()->childContexts().first(); |
| 171 | |
| 172 | auto code = createCodeRepresentation(headerUrl); |
| 173 | if (!code) { |
| 174 | return i18n("No document for %1", headerUrl.str()); |
| 175 | } |
| 176 | |
| 177 | auto bodyRange = otherCtx->rangeInCurrentRevision(); |
| 178 | |
| 179 | auto prefixRange(ClangIntegration::DUChainUtils::functionSignatureRange(decl)); |
| 180 | const auto prefixText = code->rangeText(prefixRange); |
| 181 | for (int i = prefixText.length() - 1; i >= 0 && prefixText.at(i).isSpace(); --i) { |
| 182 | if (bodyRange.start().column() == 0) { |
| 183 | bodyRange.setStart(bodyRange.start() - KTextEditor::Cursor(1, 0)); |
| 184 | if (bodyRange.start().line() == prefixRange.start().line()) { |
| 185 | bodyRange.setStart(KTextEditor::Cursor(bodyRange.start().line(), prefixRange.start().column() + i)); |
| 186 | } else { |
| 187 | int lastNewline = prefixText.lastIndexOf(QLatin1Char('\n'), i - 1); |
| 188 | bodyRange.setStart(KTextEditor::Cursor(bodyRange.start().line(), i - lastNewline - 1)); |
| 189 | } |