2013-04-28 13 views
8

Próbuję napisać narzędzie do generowania kodu. W przypadku tego narzędzia ważne jest, aby wygenerowany kod był dostępny przed rozpoczęciem budowy (tj. Dla IntelliSense). Wiem, że Visual Studio przynajmniej częściowo oceni plan budowy projektu automatycznie, aby wygenerować IntelliSense, ale nie mogę znaleźć wielu informacji na temat szczegółów.W jaki sposób Visual Studio decyduje, kiedy i jak przebudować IntelliSense?

Jako prostszy przykład, powiedzmy, że chcę wziąć wszystkie elementy z działaniem kompilacji None i skompilować je. Mam projekt takiego:

<Project [...]> 
    [...] 
    <Compile Include="Foo.cs" /> 
    <None Include="Bar.cs" /> 
</Project> 

Jednym ze sposobów, aby uzyskać Bar.cs kompilacji jest dodanie następujących do projektu:

<PropertyGroup> 
    <CoreCompileDependsOn> 
    $(CoreCompileDependsOn);IndirectCompile 
    </CoreCompileDependsOn> 
</PropertyGroup> 
<Target Name="IndirectCompile"> 
    <CreateItem Include="@(None)"> 
    <Output ItemName="Compile" TaskParameter="Include" /> 
    </CreateItem> 
</Target> 

Jeśli zrobić to w ten sposób, Visual Studio działa w zasadzie takie same tak jakby Bar.cs miał na początku akcję Bar.cs. Technologia IntelliSense jest w pełni dostępna; jeśli dokonam zmiany w Bar.cs, zostanie ona natychmiast odzwierciedlona (cóż, tak jak jest to normalne działanie w tle) w IntelliSense podczas edycji Foo.cs itd.

Jednak zamiast bezpośrednio kompilować wpis None, chcę skopiować go do katalogu obj, a następnie skompilować go z tego miejsca. Mogę to zrobić, zmieniając cel IndirectCompile do tego:

<Target Name="IndirectCompile" 
     Inputs="@(None)" 
     Outputs="@(None->'$(IntermediateOutputPath)%(FileName).g.cs')" 
> 
    <Copy SourceFiles="@(None)" 
     DestinationFiles="@(None->'$(IntermediateOutputPath)%(FileName).g.cs')" 
    > 
    <Output TaskParameter="DestinationFiles" ItemName="Compile" /> 
    </Copy> 
</Target> 

Rozwiązanie to powoduje IntelliSense zatrzymać aktualizację. Zadanie działa w oparciu o kompilację, analizę zależności i przyrostowe prace budowlane, Visual Studio zatrzymuje się automatycznie, gdy plik wejściowy zostanie zapisany.

Prowadzi to do pytania tytułowego: W jaki sposób Visual Studio decyduje się na uruchamianie celów, czy nie dla IntelliSense? Jedyną oficjalną dokumentacją, którą znalazłem, jest this, w szczególności sekcja "Design-Time IntelliSense". Jestem pewien, że mój kod spełnia wszystkie te kryteria. czego mi brakuje?

Odpowiedz

6

Po kilku dniach eksperymentowania i grzebania w debuggerze, wydaje mi się, że znalazłem odpowiedź i niestety ta odpowiedź jest taka, że ​​nie jest to możliwe (przynajmniej nie w sposób wyraźnie obsługiwany - jestem pewien, że są sposoby na oszukiwanie systemu).

Po załadowaniu projektu i zmianie samego projektu (pliki dodane/usunięte, zmiany kompilacji itp.) Wykonywana jest kompilacja IntelliSense (csproj.dll!CLangCompiler::RunIntellisenseBuild). Ta kompilacja będzie uruchamiać zadania do zadania Csc włącznie. Csc nie uruchomi się normalnie, ale zamiast tego po prostu przekazuje swoje wejścia z powrotem do hosta (Visual Studio).

Od tego momentu Visual Studio śledzi pliki, które zostały podane jako Sources do zadania Csc. Będzie monitorować te pliki w poszukiwaniu zmian, a gdy się zmienią, zaktualizuje IntelliSense. W moim przykładzie, jeśli ręcznie edytuję, zmiany te zostaną wykryte. Jednak same zadania kompilacji nie będą uruchamiane ponownie, dopóki projekt się nie zmieni lub wyraźnie zażądano kompilacji.

To chyba rozczarowujące, ale nie zaskakujące. Wyjaśnia również coś jeszcze, o czym zawsze się zastanawiałem - pliki XAML z kodem źródłowym zazwyczaj mają akcję Custom Tool pod numerem MSBuild:Compile, prawdopodobnie z tego właśnie powodu.

Zamierzam oznaczyć to jako odpowiedź, ale chciałbym usłyszeć, że jestem w błędzie i że coś przeoczyłem.

Powiązane problemy