Changeset View
Standalone View
duchain/builders/declarationbuilder.cpp
Show First 20 Lines • Show All 224 Lines • ▼ Show 20 Line(s) | 224 | typeIndex++; | |||
---|---|---|---|---|---|
225 | } | 225 | } | ||
226 | while (iter != end); | 226 | while (iter != end); | ||
227 | } | 227 | } | ||
228 | } | 228 | } | ||
229 | } | 229 | } | ||
230 | 230 | | |||
231 | void DeclarationBuilder::visitFuncDeclaration(go::FuncDeclarationAst* node) | 231 | void DeclarationBuilder::visitFuncDeclaration(go::FuncDeclarationAst* node) | ||
232 | { | 232 | { | ||
233 | go::GoFunctionDeclaration* decl = parseSignature(node->signature, true, node->funcName, m_session->commentBeforeToken(node->startToken-1)); | 233 | buildFunction(node->signature, node->body, node->funcName, m_session->commentBeforeToken(node->startToken-1)); | ||
234 | if(!node->body) | | |||
235 | return; | | |||
236 | //a context will be opened when visiting block, but we still open another one here | | |||
237 | //so we can import arguments into it.(same goes for methodDeclaration) | | |||
238 | DUContext* bodyContext = openContext(node->body, DUContext::ContextType::Function, node->funcName); | | |||
239 | {//import parameters into body context | | |||
240 | DUChainWriteLocker lock; | | |||
241 | if(decl->internalContext()) | | |||
242 | currentContext()->addImportedParentContext(decl->internalContext()); | | |||
243 | if(decl->returnArgsContext()) | | |||
244 | currentContext()->addImportedParentContext(decl->returnArgsContext()); | | |||
245 | } | | |||
246 | | ||||
247 | visitBlock(node->body); | | |||
248 | { | | |||
249 | DUChainWriteLocker lock; | | |||
250 | lastContext()->setType(DUContext::Function); | | |||
251 | decl->setInternalFunctionContext(lastContext()); //inner block context | | |||
252 | decl->setKind(Declaration::Instance); | | |||
253 | } | | |||
254 | closeContext(); //body wrapper context | | |||
255 | } | 234 | } | ||
256 | 235 | | |||
257 | void DeclarationBuilder::visitPrimaryExpr(go::PrimaryExprAst *node) | 236 | void DeclarationBuilder::visitPrimaryExpr(go::PrimaryExprAst *node) | ||
258 | { | 237 | { | ||
259 | if(node->signature && !node->convArg) // func type literal and not conversion. | 238 | if(node->signature && !node->convArg) // func type literal and not conversion. | ||
260 | { | 239 | { | ||
261 | buildFunction(node->signature, node->body); | 240 | buildFunction(node->signature, node->body); | ||
262 | } | 241 | } | ||
Show All 16 Lines | 252 | { | |||
279 | else | 258 | else | ||
280 | actualtype = node->methodRecv->nameOrType; | 259 | actualtype = node->methodRecv->nameOrType; | ||
281 | DUChainWriteLocker lock; | 260 | DUChainWriteLocker lock; | ||
282 | declaration = openDeclaration<Declaration>(identifierForNode(actualtype), editorFindRange(actualtype, 0)); | 261 | declaration = openDeclaration<Declaration>(identifierForNode(actualtype), editorFindRange(actualtype, 0)); | ||
283 | declaration->setKind(Declaration::Namespace); | 262 | declaration->setKind(Declaration::Namespace); | ||
284 | openContext(node, editorFindRange(node, 0), DUContext::Namespace, identifierForNode(actualtype)); | 263 | openContext(node, editorFindRange(node, 0), DUContext::Namespace, identifierForNode(actualtype)); | ||
285 | declaration->setInternalContext(currentContext()); | 264 | declaration->setInternalContext(currentContext()); | ||
286 | } | 265 | } | ||
287 | go::GoFunctionDeclaration* decl = parseSignature(node->signature, true, node->methodName, m_session->commentBeforeToken(node->startToken-1)); | | |||
288 | 266 | | |||
289 | if(!node->body) | 267 | auto functionDeclaration = buildFunction(node->signature, node->body, node->methodName, m_session->commentBeforeToken(node->startToken-1)); | ||
290 | return; | | |||
291 | 268 | | |||
292 | DUContext* bodyContext = openContext(node->body, DUContext::ContextType::Function, node->methodName); | 269 | if(node->methodRecv->type && functionDeclaration->internalContext()) | ||
293 | | ||||
294 | {//import parameters into body context | | |||
295 | DUChainWriteLocker lock; | | |||
296 | if(decl->internalContext()) | | |||
297 | currentContext()->addImportedParentContext(decl->internalContext()); | | |||
298 | if(decl->returnArgsContext()) | | |||
299 | currentContext()->addImportedParentContext(decl->returnArgsContext()); | | |||
300 | } | | |||
301 | | ||||
302 | if(node->methodRecv->type) | | |||
303 | {//declare method receiver variable('this' or 'self' analog in Go) | 270 | {//declare method receiver variable('this' or 'self' analog in Go) | ||
271 | openContext(functionDeclaration->internalContext()); | ||||
304 | buildTypeName(node->methodRecv->type); | 272 | buildTypeName(node->methodRecv->type); | ||
305 | if(node->methodRecv->star!= -1) | 273 | if(node->methodRecv->star!= -1) | ||
306 | { | 274 | { | ||
307 | PointerType* ptype = new PointerType(); | 275 | PointerType* ptype = new PointerType(); | ||
308 | ptype->setBaseType(lastType()); | 276 | ptype->setBaseType(lastType()); | ||
309 | injectType(PointerType::Ptr(ptype)); | 277 | injectType(PointerType::Ptr(ptype)); | ||
310 | } | 278 | } | ||
311 | DUChainWriteLocker n; | 279 | DUChainWriteLocker n; | ||
312 | Declaration* thisVariable = openDeclaration<Declaration>(identifierForNode(node->methodRecv->nameOrType), editorFindRange(node->methodRecv->nameOrType, 0)); | 280 | Declaration* thisVariable = openDeclaration<Declaration>(identifierForNode(node->methodRecv->nameOrType), editorFindRange(node->methodRecv->nameOrType, 0)); | ||
313 | thisVariable->setAbstractType(lastType()); | 281 | thisVariable->setAbstractType(lastType()); | ||
314 | closeDeclaration(); | 282 | closeDeclaration(); | ||
283 | closeContext(); | ||||
315 | } | 284 | } | ||
316 | 285 | | |||
317 | visitBlock(node->body); | | |||
318 | { | | |||
319 | DUChainWriteLocker lock; | | |||
320 | lastContext()->setType(DUContext::Function); | | |||
321 | decl->setInternalFunctionContext(lastContext()); //inner block context | | |||
322 | decl->setKind(Declaration::Instance); | | |||
323 | } | | |||
324 | | ||||
325 | closeContext(); //body wrapper context | | |||
326 | closeContext(); //namespace | 286 | closeContext(); //namespace | ||
327 | closeDeclaration(); //namespace declaration | 287 | closeDeclaration(); //namespace declaration | ||
328 | } | 288 | } | ||
329 | 289 | | |||
330 | void DeclarationBuilder::visitTypeSpec(go::TypeSpecAst* node) | 290 | void DeclarationBuilder::visitTypeSpec(go::TypeSpecAst* node) | ||
331 | { | 291 | { | ||
332 | //first try setting comment before type name | 292 | //first try setting comment before type name | ||
333 | //if it doesn't exists, set comment before type declaration | 293 | //if it doesn't exists, set comment before type declaration | ||
▲ Show 20 Lines • Show All 269 Lines • ▼ Show 20 Line(s) | |||||
603 | { | 563 | { | ||
604 | m_lastTypeComment = m_session->commentBeforeToken(node->startToken); | 564 | m_lastTypeComment = m_session->commentBeforeToken(node->startToken); | ||
605 | go::DefaultVisitor::visitTypeDecl(node); | 565 | go::DefaultVisitor::visitTypeDecl(node); | ||
606 | m_lastTypeComment = QByteArray(); | 566 | m_lastTypeComment = QByteArray(); | ||
607 | } | 567 | } | ||
608 | 568 | | |||
609 | 569 | | |||
610 | go::GoFunctionDeclaration* DeclarationBuilder::declareFunction(go::IdentifierAst* id, const go::GoFunctionType::Ptr& type, | 570 | go::GoFunctionDeclaration* DeclarationBuilder::declareFunction(go::IdentifierAst* id, const go::GoFunctionType::Ptr& type, | ||
611 | DUContext* paramContext, DUContext* retparamContext, const QByteArray& comment) | 571 | DUContext* paramContext, DUContext* retparamContext, const QByteArray& comment, DUContext* bodyContext) | ||
612 | { | 572 | { | ||
613 | setComment(comment); | 573 | setComment(comment); | ||
614 | DUChainWriteLocker lock; | 574 | DUChainWriteLocker lock; | ||
615 | go::GoFunctionDeclaration* dec = openDefinition<go::GoFunctionDeclaration>(identifierForNode(id), editorFindRange(id, 0)); | 575 | go::GoFunctionDeclaration* dec = openDefinition<go::GoFunctionDeclaration>(identifierForNode(id), editorFindRange(id, 0)); | ||
616 | dec->setType<go::GoFunctionType>(type); | 576 | dec->setType<go::GoFunctionType>(type); | ||
617 | //dec->setKind(Declaration::Type); | | |||
618 | dec->setKind(Declaration::Instance); | 577 | dec->setKind(Declaration::Instance); | ||
619 | dec->setInternalContext(paramContext); | 578 | dec->setInternalContext(bodyContext); | ||
579 | | ||||
580 | if(bodyContext) | ||||
581 | { | ||||
582 | if(paramContext) | ||||
583 | { | ||||
584 | bodyContext->addImportedParentContext(paramContext); | ||||
585 | dec->setInternalFunctionContext(paramContext); | ||||
586 | } | ||||
620 | if(retparamContext) | 587 | if(retparamContext) | ||
mwolff: a context for the return parameter? is that really required? just asking out of curiosity… | |||||
I think that it's handful because in Go language "named result parameters " exists: https://golang.org/doc/effective_go.html#named-results. ematirov: I think that it's handful because in Go language "named result parameters " exists: https… | |||||
588 | { | ||||
589 | bodyContext->addImportedParentContext(retparamContext); | ||||
621 | dec->setReturnArgsContext(retparamContext); | 590 | dec->setReturnArgsContext(retparamContext); | ||
622 | //dec->setInternalFunctionContext(bodyContext); | 591 | } | ||
592 | } | ||||
593 | | ||||
623 | closeDeclaration(); | 594 | closeDeclaration(); | ||
624 | return dec; | 595 | return dec; | ||
625 | } | 596 | } | ||
626 | 597 | | |||
598 | go::GoFunctionDeclaration* DeclarationBuilder::buildFunction(go::SignatureAst* node, go::BlockAst* block, go::IdentifierAst* name, const QByteArray& comment) | ||||
599 | { | ||||
600 | DUContext* bodyContext = nullptr; | ||||
601 | if(block) | ||||
602 | { | ||||
603 | visitBlock(block); | ||||
604 | bodyContext = lastContext(); | ||||
605 | } | ||||
606 | return parseSignature(node, true, bodyContext, name, comment); | ||||
are you sure that this always creates a context? i.e. even if the user typed somewhat broken code into the editor? I suggest you better rewrite this like the below, to be on the safe side: if (block) { visitBlock(block); DUChainWriteLocker lock; bodyContext = lastContext(); if (bodyContext) { bodyContext->setType(DUContext::Other); } } better yet, could you set this type directly wherever you are creating the context itself? from a cursory glance, I don't even see where this is done mwolff: are you sure that this always creates a context? i.e. even if the user typed somewhat broken… | |||||
You were right, there is no need for calling setType since visitBlock already opens context with correct type. ematirov: You were right, there is no need for calling setType since visitBlock already opens context… | |||||
607 | } | ||||
608 | No newline at end of file |
a context for the return parameter? is that really required? just asking out of curiosity, afaik the other language plugins don't do that (or?)