/****************************************************************************
|
**
|
** Copyright (C) 2018 The Qt Company Ltd.
|
** Contact: https://www.qt.io/licensing/
|
**
|
** This file is part of the Qt VS Tools.
|
**
|
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
** Commercial License Usage
|
** Licensees holding valid commercial Qt licenses may use this file in
|
** accordance with the commercial license agreement provided with the
|
** Software or, alternatively, in accordance with the terms contained in
|
** a written agreement between you and The Qt Company. For licensing terms
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
** information use the contact form at https://www.qt.io/contact-us.
|
**
|
** GNU General Public License Usage
|
** Alternatively, this file may be used under the terms of the GNU
|
** General Public License version 3 as published by the Free Software
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
** included in the packaging of this file. Please review the following
|
** information to ensure the GNU General Public License requirements will
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
**
|
** $QT_END_LICENSE$
|
**
|
****************************************************************************/
|
|
using System;
|
using System.IO;
|
using Microsoft.VisualStudio;
|
using Microsoft.VisualStudio.Debugger.Interop;
|
|
namespace QtVsTools.Qml.Debug.AD7
|
{
|
sealed partial class CodeContext :
|
|
IDebugDocumentContext2, // "This interface represents a position in a source file document."
|
|
IDebugCodeContext2, // "This interface represents the starting position of a code
|
IDebugCodeContext100 // instruction. For most run-time architectures today, a code
|
// context can be thought of as an address in a program's execution
|
// stream."
|
{
|
public QmlEngine Engine { get; private set; }
|
public Program Program { get; private set; }
|
|
public string FilePath { get; private set; }
|
public uint FileLine { get; private set; }
|
|
public enum Language { QML, JavaScript, Other }
|
public Language FileType
|
{
|
get
|
{
|
var ext = Path.GetExtension(FilePath);
|
if (string.Equals(ext, ".qml", StringComparison.InvariantCultureIgnoreCase))
|
return Language.QML;
|
if (string.Equals(ext, ".js", StringComparison.InvariantCultureIgnoreCase))
|
return Language.JavaScript;
|
return Language.Other;
|
}
|
}
|
|
public static CodeContext Create(
|
QmlEngine engine, Program program,
|
string filePath, uint fileLine)
|
{
|
return new CodeContext()
|
{
|
Engine = engine,
|
Program = program,
|
FilePath = filePath,
|
FileLine = fileLine
|
};
|
}
|
|
private CodeContext()
|
{ }
|
|
class CodeContextInfo : InfoHelper<CodeContextInfo>
|
{
|
public string Address { get; set; }
|
}
|
|
CodeContextInfo Info
|
{
|
get
|
{
|
return new CodeContextInfo
|
{
|
Address = FileLine.ToString()
|
};
|
}
|
}
|
|
static readonly CodeContextInfo.Mapping MappingToCONTEXT_INFO =
|
|
#region //////////////////// CONTEXT_INFO <-- CodeContextInfo /////////////////////////////
|
// r: Ref<CONTEXT_INFO>
|
// f: enum_CONTEXT_INFO_FIELDS
|
// i: CodeContextInfo
|
// v: value of i.<<property>>
|
|
new CodeContextInfo.Mapping<CONTEXT_INFO, enum_CONTEXT_INFO_FIELDS>
|
((r, f) => r.s.dwFields |= f)
|
{
|
{ enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS,
|
(r, v) => r.s.bstrAddress = v, i => i.Address }
|
};
|
|
#endregion //////////////////// CONTEXT_INFO <-- CodeContextInfo //////////////////////////
|
|
|
public int /*IDebugCodeContext2*/ GetInfo(
|
enum_CONTEXT_INFO_FIELDS dwFields,
|
CONTEXT_INFO[] pinfo)
|
{
|
Info.Map(MappingToCONTEXT_INFO, dwFields, out pinfo[0]);
|
return VSConstants.S_OK;
|
}
|
|
public int /*IDebugCodeContext2*/ Compare(
|
enum_CONTEXT_COMPARE Compare,
|
IDebugMemoryContext2[] rgpMemoryContextSet,
|
uint dwMemoryContextSetLen,
|
out uint pdwMemoryContext)
|
{
|
pdwMemoryContext = uint.MaxValue;
|
if (Compare != enum_CONTEXT_COMPARE.CONTEXT_EQUAL)
|
return VSConstants.E_NOTIMPL;
|
|
for (uint i = 0; i < dwMemoryContextSetLen; ++i) {
|
var that = rgpMemoryContextSet[i] as CodeContext;
|
if (that == null)
|
continue;
|
if (this.Engine != that.Engine)
|
continue;
|
if (this.Program != that.Program)
|
continue;
|
if (!string.Equals(
|
Path.GetFullPath(this.FilePath), Path.GetFullPath(that.FilePath),
|
StringComparison.InvariantCultureIgnoreCase)) {
|
continue;
|
}
|
if (this.FileLine != that.FileLine)
|
continue;
|
|
pdwMemoryContext = i;
|
return VSConstants.S_OK;
|
}
|
|
return VSConstants.S_FALSE;
|
}
|
|
int IDebugDocumentContext2.GetName(enum_GETNAME_TYPE gnType, out string pbstrFileName)
|
{
|
pbstrFileName = FilePath;
|
return VSConstants.S_OK;
|
}
|
|
int IDebugDocumentContext2.GetStatementRange(
|
TEXT_POSITION[] pBegPosition,
|
TEXT_POSITION[] pEndPosition)
|
{
|
pBegPosition[0].dwLine = FileLine;
|
pBegPosition[0].dwColumn = 0;
|
pEndPosition[0].dwLine = FileLine;
|
pEndPosition[0].dwColumn = 0;
|
return VSConstants.S_OK;
|
}
|
|
int IDebugDocumentContext2.EnumCodeContexts(out IEnumDebugCodeContexts2 ppEnumCodeCxts)
|
{
|
ppEnumCodeCxts = CodeContextEnum.Create(this);
|
return VSConstants.S_OK;
|
}
|
|
int IDebugDocumentContext2.GetLanguageInfo(
|
ref string pbstrLanguage,
|
ref Guid pguidLanguage)
|
{
|
pbstrLanguage = "C++";
|
pguidLanguage = NativeEngine.IdLanguageCpp;
|
return VSConstants.S_OK;
|
}
|
|
int IDebugCodeContext2.GetLanguageInfo(ref string pbstrLanguage, ref Guid pguidLanguage)
|
{
|
return (this as IDebugDocumentContext2)
|
.GetLanguageInfo(ref pbstrLanguage, ref pguidLanguage);
|
}
|
|
int IDebugCodeContext2.GetDocumentContext(out IDebugDocumentContext2 ppSrcCxt)
|
{
|
ppSrcCxt = this;
|
return VSConstants.S_OK;
|
}
|
|
int IDebugCodeContext100.GetProgram(out IDebugProgram2 ppProgram)
|
{
|
ppProgram = Program;
|
return VSConstants.S_OK;
|
}
|
}
|
}
|